Leetcode 5.最长回文子串
1 题目描述(Leetcode题目链接)
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。示例:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
2 题解
本题可以使用动态规划的方法,子串不是子序列,需要连续,因此可以定义
D
P
[
i
]
[
j
]
DP[i][j]
DP[i][j]为字符
i
i
i到
j
j
j组成的字符串是否为回文子串,因此
D
P
[
i
]
[
j
]
DP[i][j]
DP[i][j]的状态转移方程如下:
D
P
[
i
]
[
j
]
=
{
1
i
f
s
[
i
]
=
=
s
[
j
]
a
n
d
D
P
[
i
+
1
]
[
j
−
1
]
=
=
1
0
o
t
h
e
r
w
i
s
e
DP[i][j] = \begin{cases}1 &if &s[i]==s[j]\ and \ DP[i+1][j-1] ==1 \\0&&otherwise\end{cases}
DP[i][j]={10ifs[i]==s[j] and DP[i+1][j−1]==1otherwise
同时记录一个最长子串的下标范围用于输出。
class Solution:
def longestPalindrome(self, s: str) -> str:
length = len(s)
DP = [([1]*length) for i in range(length)]
max_size = 0
retv = [0,0]
i = length - 2
while i >= 0:
for j in range(i+1, length):
if s[i] == s[j] and DP[i+1][j-1] == 1:
DP[i][j] = 1
if j - i >= max_size:
max_size = j - i
retv[0] = i; retv[1] = j
else:
DP[i][j] = 0
i -= 1
return s[retv[0]:retv[1]+1]
Manacher算法解决最长回文子串问题。
class Solution:
def longestPalindrome(self, s: str) -> str:
new_s = "$#" + "#".join(list(s)) + "#%"
index, max_len = 0, 0
center = 0
radius = 0
arr = [0]*len(new_s)
for i in range(1, len(new_s) - 1):
if i < radius:
arr[i] = min(arr[2*center - i], radius - i)
else:
arr[i] = 1
while new_s[i - arr[i]] == new_s[i + arr[i]]:
arr[i] += 1
if i + arr[i] > radius:
radius = i + arr[i]
center = i
if arr[i] - 1 > max_len:
max_len = arr[i] - 1
index = i
return "".join(new_s[index - max_len:index + max_len].split("#"))