返回
LeetCode最长回文子串:算法练习系列,迎接复杂挑战!
前端
2024-02-16 12:05:27
导语
欢迎来到算法练习系列的第五天!今天,我们将踏上LeetCode最长回文子串的征程,这是一道难度较高的算法题,但只要充分考虑各种情况,你就能避免不断踩坑。
问题陈述
给你一个字符串 s
,请你找出其中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是回文串,但 "bab" 更长。
示例 2:
输入:s = "cbbd"
输出:"bb"
示例 3:
输入:s = "a"
输出:"a"
示例 4:
输入:s = "ac"
输出:"a"
算法讲解
解决最长回文子串问题,有以下三种算法:
- 中心扩展算法 :从字符串的中心开始向两侧扩展,直到找到最长的回文子串。
- 马拉车算法 :预处理字符串,然后使用动态规划来计算最长回文子串。
- KMP算法 :将字符串转换为一个新的字符串,然后使用KMP算法来找到最长的回文子串。
算法实现
中心扩展算法
def longest_palindrome(s):
def expand_around_center(left, right):
while left >= 0 and right < len(s) and s[left] == s[right]:
left -= 1
right += 1
return s[left + 1:right]
longest = ""
for i in range(len(s)):
# 以单个字符为中心扩展
palindrome1 = expand_around_center(i, i)
# 以相邻两个字符为中心扩展
palindrome2 = expand_around_center(i, i + 1)
longest = max(longest, palindrome1, palindrome2, key=len)
return longest
马拉车算法
def longest_palindrome(s):
n = len(s)
dp = [[False] * n for _ in range(n)]
# 初始化单个字符为回文子串
for i in range(n):
dp[i][i] = True
# 长度为2的回文子串
for i in range(n - 1):
if s[i] == s[i + 1]:
dp[i][i + 1] = True
# 长度大于2的回文子串
max_length = 1
start = 0
for k in range(3, n + 1):
for i in range(n - k + 1):
j = i + k - 1
if s[i] == s[j] and dp[i + 1][j - 1]:
dp[i][j] = True
if k > max_length:
max_length = k
start = i
return s[start:start + max_length]
KMP算法
def longest_palindrome(s):
# 预处理字符串
new_s = "#" + "#".join(s) + "#"
# 计算最长公共前缀
n = len(new_s)
p = [0] * n
for i in range(1, n):
j = p[i - 1]
while j > 0 and new_s[i] != new_s[j]:
j = p[j - 1]
if new_s[i] == new_s[j]:
j += 1
p[i] = j
# 找到最长的回文子串
max_length = 0
start = 0
for i in range(1, n):
if p[i] > max_length:
max_length = p[i]
start = (i - max_length) // 2
return s[start:start + max_length]
总结
最长回文子串问题是算法练习中的经典问题,它有中心扩展算法、马拉车算法和KMP算法三种解法。掌握这些算法,你将成为算法练习中的高手!