题目描述
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。
示例 1:
输入: "babad" 输出: "bab" 注意: "aba"也是一个有效答案。
示例 2:
输入: "cbbd" 输出: "bb"
思路
回文子串:正读,反读都是一样的序列。
一次把每个字符当做回文子串中的中间字符,以此向外扩,同步左右相同的字符,回文子串增长。
回文子串的长度要分奇偶来考虑,但无论是奇数长度还是偶数长度,都是对比第一位=倒数第一位,第二位等于倒数第二位,第三位等于倒数第三位,....二者主要的不同在于回文子串的边界的定义,n-i在奇数长度的子串中表示不能超过原字符串的边界,i+1表示从i字符的左边的元素个数包含i字符,从二者中取其小,保证i字符往外扩的字符个数不能超过原字符的边界。偶数长度的子串中,i字符和i+1字符作为回文子串中的中间子串,i字符的左侧字符(包含i字符)个数是i+1,右侧字符的个数是n-i-1(抛去了i+1字符)。最后的右侧边界分别为r=i+j+1,和r=i+j+2。
代码实现
class Solution:
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
#第一种思路:对比s和s的逆序列,找公共子串
#第二种思路:找出所有子串,然后对比第一位与倒数第一位,第二位与倒数第二位...
n = len(s)
l, r, m, c=0,0,0,0 #l:回文子串中的左边界,r:回文子串中的右边界,M:当前最长回文子串的长度,c:当前子串的长度
#b = True #子串是否包含首字符或者末字符且是回文序列
for i in range(n):
for j in range(min(n-i,i+1)): #i+1是与当前的 i字符距离1个距离的字符位置,n-i是i字符到字符串的边界
if s[i-j]!=s[i+j]:
break
else:
c=2*j+1
if (c>m):
l = i-j
r = i+j+1
m = c
for j in range(min(n-i-1,i+1)):
if s[i-j] != s[i+j+1]:
break
else:
c=2*j+2
if (c>m):
l = i-j
r = i+j+2
m = c
return s[l:r]