AI刷题402:小M的最长回文子串挑战题目解析 | 豆包MarsCode AI刷题

113 阅读3分钟

题目:402-小M的最长回文子串挑战 题目解析

问题描述

小M发现了一个神奇的现象,她手中有一个字符串 s,她想知道这个字符串中最长的回文子串的长度是多少。你的任务是帮助小M找到该字符串的最长回文子串,并返回它的长度。

回文子串是指从左到右和从右到左字符顺序相同的字符串。

测试样例

样例1:

输入:s = "abcbadb"
输出:5

样例2:

输入:s = "ababacab"
输出:5

样例3:

输入:s = "racecarwk"
输出:7


问题理解

  • 给定一个字符串,需要找出其中最长的回文子串的长度
  • 回文串指正着读和反着读都一样的字符串
  • 需要考虑所有可能的子串,找出最长的回文子串长度

解题思路

动态规划基本思想

这道题采用动态规划的方法解决,主要思路如下:

  1. 使用二维数组dp[i][j]表示字符串从位置i到j的子串是否为回文串
  2. 从小到大遍历子串长度,逐步判断各个长度的子串是否为回文串

动态规划状态设计

  1. 状态定义:
    • dp[i][j]表示s[i:j+1]是否为回文串(布尔值)
  2. 初始状态:
    • 单个字符都是回文串:dp[i][i] = True

状态转移方程

对于长度大于1的子串,状态转移方程为:

dp[i][j] = (s[i] == s[j] and dp[i+1][j-1])

特殊情况:当子串长度为2时,只需判断两个字符是否相同:

dp[i][j] = (s[i] == s[j])

代码实现步骤

基础框架设置

def solution(s: str) -> int:
    if not s:
        return 0
    n = len(s)
    max_len = 1  # 初始化最大长度为1
    dp = [[False] * n for _ in range(n)]  # 创建dp数组

初始化单字符情况

# 单个字符都是回文串
for i in range(n):
    dp[i][i] = True

遍历所有可能的子串

for length in range(2, n + 1):  # 遍历所有可能的长度
    for start in range(n - length + 1):  # 遍历所有起始位置
        end = start + length - 1

判断子串是否为回文

if length == 2:
    dp[start][end] = (s[start] == s[end])
else:
    dp[start][end] = (s[start] == s[end] and dp[start + 1][end - 1])

更新最大长度

if dp[start][end]:
    max_len = max(max_len, length)

复杂度分析

  • 时间复杂度:O(n²),其中n为字符串长度
  • 空间复杂度:O(n²),需要n×n的dp数组

收获

  1. 如果字符串很长,可以考虑使用中心扩展法来降低空间复杂度
  2. 可以在发现更长的回文串时记录起始位置,方便返回具体的回文子串
  3. 可以添加提前退出的条件,如果已找到长度为n的回文串,就不需要继续搜索了

完整代码

def solution(s: str) -> int:
    if not s:
        return 0
        
    # 初始化最大长度为1
    max_len = 1
    n = len(s)
    
    # dp[i][j]表示s[i:j+1]是否为回文串
    dp = [[False] * n for _ in range(n)]
    
    # 单个字符都是回文串
    for i in range(n):
        dp[i][i] = True
    
    # 遍历所有可能的长度
    for length in range(2, n + 1):
        # 遍历所有起始位置
        for start in range(n - length + 1):
            end = start + length - 1
            
            # 如果长度为2,只需判断两个字符是否相同
            if length == 2:
                dp[start][end] = (s[start] == s[end])
            else:
                # 当前字符相同且子串为回文时,当前串为回文
                dp[start][end] = (s[start] == s[end] and dp[start + 1][end - 1])
                
            # 更新最大长度
            if dp[start][end]:
                max_len = max(max_len, length)
                
    return max_len

if __name__ == '__main__':
    print(solution("abcbadb") == 5)
    print(solution("ababacab") == 5) 
    print(solution("racecarwk") == 7)