题目描述:
给你一个字符串 s,找到 s 中最长的回文子串。
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
分析:
这是经典的动态规划题目,动态规划的具体定义就不赘述了,但是最重要的关键就是动态方程的设计。我们可以分析一下,如果一个字串是回文的,如果该字串的前一个字符和后一个字符是相同的,那么这个字串加2也是回文的。这里我们分析的其实是转移情况,那么初始的动态函数,我们只需要判断字串是否是回文串。
p
[
i
,
j
]
=
{
T
u
r
e
s
i
.
.
.
s
j
是
回
文
串
F
a
l
s
e
其
他
情
况
p[i,j]=\begin{cases}Ture&s_i...s_j 是回文串\\False&其他情况\end{cases}
p[i,j]={TureFalsesi...sj是回文串其他情况
那么转移函数就是:
p
[
i
,
j
]
=
p
[
i
+
1
,
j
−
1
]
&
(
s
i
=
=
s
j
)
p[i,j]=p[i+1,j-1]\&(s_i==s_j)
p[i,j]=p[i+1,j−1]&(si==sj)
然后对于边界情况如果长度为1,那么就是回文串,如果长度为2,两个字符需要相同。
p
[
i
,
j
]
=
{
T
u
r
e
i
=
=
j
T
u
r
e
i
=
=
j
−
1
并
且
s
i
=
=
s
j
−
1
p[i,j]=\begin{cases}Ture&i==j\\Ture&i==j-1并且s_i ==s_j-1\end{cases}
p[i,j]={TureTurei==ji==j−1并且si==sj−1
基于此,我们得到实践。
class Solution:
def longestPalindrome(self, s: str) -> str:
l = len(s)
if l < 2:
return s
p = [[False]*l for _ in range(l)]
le = 0
ri = 0
%用来保存最长的回文字串的左边和右边的位置
for i in range(l):
p[i][i] = True
%长度为一的为True
if i < l - 1:
if s[i] == s[i+1]:
le = i
ri = i + 1
p[i][i+1] = True
%长度为2的回文字串
for L in range(3, l + 1):
%从长度为3的字串开始
for left in range(l):
right = L + left - 1
if right < l:
if s[left] == s[right] and p[left + 1][right - 1] == True:
p[left][right] = True
le = left
ri = right
else:
p[left][right] = False
return s[le:ri+1]
但是结果一般: