题目
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
【分析】本题有多种方法,例如中心扩散法,马拉车(Manacher)算法,动态规划法。
个人理解中心扩散法和马拉车算法都类似。其核心思想都是利用双指针从中间向两边开始判断是否符合回文串特征(左右对称)。
回文串有两种,一种是奇数长度的回文串,一种是偶数长度的回文串。奇数长度的是从中间某个元素开始向两边扩散(s[left]==s[right]),偶数长度的是从中间某两个元素开始向两边扩散。
所以在中心扩散法中分两种情况,一种是奇数回文串时,left=right开始迭代;另一种是偶数回文串时,right=left+1开始迭代。
而在马拉车算法中,把所有的字符串长度全部化为奇数的情况:添加分隔符。然后left=right同时向两边迭代,直到遇到边界条件为止。
class Solution:
def longestPalindrome(self, s):
s='#'+'#'.join(s)+'#' #添加分隔符
size=len(s)
if len(s)==2:
return ""
p=[] #得到p数组
for i in range(size):
left=i
right=i
while left>=0 and right<size and s[left]==s[right]:
left-=1
right+=1
p.append(right-i)
i=p.index(max(p))
return ''.join(s[i-p[i]+1:i+p[i]-1].split("#"))
【动态规划法】首先定义状态,设
f
(
i
,
j
)
f(i,j)
f(i,j)表示子串
s
[
i
,
j
]
s[i,j]
s[i,j]是否是回文串,若是则为1,否则为0;
其次确定状态转移方程:
f
(
i
,
j
)
=
{
s
[
i
]
=
=
s
[
j
]
,
j
−
i
≤
1
s
[
i
]
=
=
s
[
j
]
a
n
d
f
(
i
+
1
,
j
−
1
)
=
=
1
,
j
−
i
>
1
f(i,j)=\left\{\begin{matrix} s[i]==s[j],\quad \quad \quad \quad \quad \quad \quad \quad \quad \quad \quad \quad j-i\leq 1 \\ s[i]==s[j] \quad and \quad f(i+1,j-1)==1,j-i>1 \end{matrix}\right.
f(i,j)={s[i]==s[j],j−i≤1s[i]==s[j]andf(i+1,j−1)==1,j−i>1
直观上,
- i i i为内循环, j j j为外循环; i ≤ j i \leq j i≤j,同时保证在得到 f ( i + 1 , j − 1 ) f(i+1,j-1) f(i+1,j−1)的基础上再来得出 f ( i , j ) f(i,j) f(i,j)的结果(所以先循环 j : r a n g e ( l e n ( s ) ) j:range(len(s)) j:range(len(s)),再循环 i : r a n g e ( j + 1 ) ) i:range(j+1)) i:range(j+1))。
- 因为$ f(i,j)==1 一 定 会 有 一定会有 一定会有 f(i+1,j-1)==1 , 所 以 先 保 证 ,所以先保证 ,所以先保证 f(i+1,j-1)==1 , 然 后 判 断 子 串 的 首 尾 ,然后判断子串的首尾 ,然后判断子串的首尾s[i]==s[j]$ ,由此来得出$ f(i,j)$
class Solution:
def longestPalindrome(self, s: str) -> str:
size = len(s)
if size<=1:
return s
dp=[[0]*size for _ in range(size)]
len_max=1 #记录最大回文串的长度
index=0 #记录最大回文串的首字符索引
for j in range(size):
for i in range(j+1):
## 状态转移:
if j-i<=1 and s[i]==s[j]:
dp[i][j]=1
elif j-i>1 and s[i]==s[j] and dp[i+1][j-1]==1:
dp[i][j]=1
##记录最大回文串信息:
if dp[i][j]==1:
if j-i+1>len_max:
len_max=j-i+1
index=i
return s[index:len_max+index]