Leetcode Link: 5. 最长回文子串 - 力扣(LeetCode) (leetcode-cn.com)
题目
给你一个字符串 s,找到 s 中最长的回文子串。

解法一
思路:滑动窗口的变体 + 对向双指针 遍历字符串的每一个元素,并以每一个元素为中心采用对向双指针,往两边走,对位不等时上一个状态即为一个回文子串
题解:时间 , 空间
class Solution:
def longestPalindrome(self, s: str) -> str:
def check(l, r):
nonlocal s, res
while(1):
# 注意越界检查
if l>=0 and r<len(s) and s[l]==s[r]:
l -= 1
r += 1
else:
# 说明*上一次*的结果满足要求
# 即使刚进来都不满足要求,也可以处理,如 输入 3,4, s[3] != s[4]
# 那么此时就不会满足 if 条件,不更新res
l = l + 1
r = r - 1
if r-l+1 > res[1] - res[0]:
res = [l, r+1]
break
# 结果
res = [0,0]
for l in range(len(s)):
check(l,l) # 中心重合
check(l,l+1) # 中心相邻
return s[res[0]:res[1]]解法二
思路:动态规划 这个可能是样本对应模型
动规五步走
dp[i][j]含义:s[i:j+1]是不是回文子串 (TrueorFalse)- 递归公式:
dp[L][R]=True if s[L]==s[R] and dp[L+1][R-1] is True else False - 初始化:对角线为
True,同时相邻两个的位置也要提前初始化,否则需要在主循环中进行判断 - 遍历顺序:行倒着来,列正常。并且避免已经初始化的位置。
- 举例 题解:
class Solution:
def longestPalindrome(self, s: str) -> str:
dp = [[False for _ in range(len(s))] for _ in range(len(s))]
res = [0,0] # 记录子串的左右边界(都含)
for i in range(len(s)):
dp[i][i] = True
if i+1<len(s) and s[i]==s[i+1]:
dp[i][i+1] = True
res = [i,i+1] # 这里一定记得更新结果,在初始化时如果出现相邻的最大,那当目前为止的最长回文一定是这个
for L in range(len(s)-3, -1, -1): # 注意倒着来,跳过已经初始化的
for R in range(L+2, len(s)):
if s[L] == s[R] and dp[L+1][R-1] is True:
dp[L][R] = True
if R-L+1 > res[1]-res[0]+1:
res = [L, R]
return s[res[0]:res[1]+1]复习时想用一维dp,dp[i]表示以i位结尾的最长回文子串长度。但是失败了
启发和联系
在动规归中,如果使用dp的含义是[L,R]上的回文子串长度,一定注意需要判断[L+1,R-1]是不是回文子串,即dp[L+1][R-1]>0,然后再+2,如果只判断两者是不是相等就+2,结果会出错,因为你不知道上一个是不是回文就加。