最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:
输入:s = “cbbd”
输出:“bb”
示例 3:
输入:s = “a”
输出:“a”
示例 4:
输入:s = “ac”
输出:“a”
动态规划
def longestPalindrome(s):
n = len(s)
if n < 2:
return s
dp = [[False] * n for _ in range(n)]
start, max_len = 0, 1
for right in range(n):
for left in range(0, right + 1):
span = right - left + 1
if span == 1:
dp[left][right] = True
elif span == 2:
dp[left][right] = s[left] == s[right]
else:
dp[left][right] = dp[left + 1][right - 1] and s[left] == s[right]
if dp[left][right]:
if span > max_len:
max_len = span
start = left
return s[start: start + max_len]
初始化dp:全为False
输入以‘abba’为例:
遍历字符串,双层循环:
right=0
left=0
right=1
left=0, 1
right=2
left=0,1,2
right=3
left=0,1,2,3
第一次循环:
right=0,left=0,span=1 此时对应的子串是‘a’,是回文串,所以更改列表中的值dp[0][0]=True
此时dp[left][right]为True,更新max_len的值为span
第二次循环:
right=1,left=0,span=2 此时对应的子串是‘ab’,不是回文串,列表中的值dp[0][1]=False不变
第三次循环:
right=1,left=1,span=1 此时对应的子串是‘b’,是回文串,列表中的值dp[1][1]=True
此时dp[left][right]为True,更新max_len的值为span
第四次循环:
right=2,left=0,span=3 此时对应的子串是‘abb’,不是回文串,列表中的值dp[0][2]=False不变
第五次循环:
right=2,left=1,span=2 此时对应的子串是‘bb’,是回文串,列表中的值dp[1][2]=True
此时dp[left][right]为True,更新max_len的值为span=2
第六次循环:
right=2,left=2,span=1 此时对应的子串是‘b’,是回文串,列表中的值dp[2][2]=True
此时dp[left][right]为True,更新max_len的值
第七次循环:
right=3,left=0,span=4 此时对应的子串是‘abba’,是回文串
- 判断是否为回文串?
根据span,
span=1,只有一个字符,肯定是回文串;
span=2,若两个字符相同,则是回文串;
span=3,最左和最右两个字符相同;
span=4,中间span为2的子串是回文子串,且最左和最右两个字符相同;
span=5,中间span为3的子串是回文子串,且最左和最右两个字符相同;
span=5,中间span为4的子串是回文子串,且最左和最右两个字符相同;
… …
dp[left][right] = dp[left + 1][right - 1] and s[left] == s[right]
以此类推。
对于‘abba’,‘bb’是回文串(dp[1][2]=True),且s[0]=s[3]=‘a’
所以,dp[0][3]=True
此时dp[left][right]为True,更新max_len的值=span=4
第八次循环:
right=3,left=1,span=3 此时对应的子串是‘bba’,不是回文串
第九次循环:
right=3,left=2,span=2 此时对应的子串是‘ba’,不是回文串
第十次循环:
right=3,left=3,span=1 此时对应的子串是‘a’,是回文串,dp[3][3]=True
max_len=4
返回子串。