📅  最后修改于: 2023-12-03 15:10:37.498000             🧑  作者: Mango
回文串指一个字符串正着读和倒着读是一样的,最长回文子串指在一个字符串中,找到一个最长的回文子串。例如,在字符串 "racecar" 中,最长的回文子串是 "racecar"。
暴力破解法是寻找所有可能的子串,判断其是否为回文串,时间复杂度为O(n^3)。
代码示例:
def longest_palindrome(s: str) -> str:
n = len(s)
ans = ""
for i in range(n):
for j in range(i, n):
if s[i:j+1] == s[i:j+1][::-1]:
if len(s[i:j+1]) > len(ans):
ans = s[i:j+1]
return ans
中心扩展法通过枚举所有可能的回文中心位置,然后向两端扩展,时间复杂度为O(n^2)。
代码示例:
def longest_palindrome(s: str) -> str:
n = len(s)
ans = ""
for i in range(n):
# 寻找以i为中心的回文串
left, right = i, i
while left >= 0 and right < n and s[left] == s[right]:
left -= 1
right += 1
if right - left - 1 > len(ans):
ans = s[left+1:right]
# 寻找以i和i+1为中心的回文串
left, right = i, i+1
while left >= 0 and right < n and s[left] == s[right]:
left -= 1
right += 1
if right - left - 1 > len(ans):
ans = s[left+1:right]
return ans
马拉车算法(Manacher's Algorithm)是O(n)的算法,通过利用回文串的对称性,快速找到以每个位置为中心的回文子串,从而求出整个最长回文子串。
代码示例:
def longest_palindrome(s: str) -> str:
t = "^#" + "#".join(s) + "#$"
n = len(t)
p = [0] * n
center = right = 0
for i in range(1, n-1):
if i < right:
p[i] = min(right - i, p[2*center - i])
while t[i+p[i]+1] == t[i-p[i]-1]:
p[i] += 1
if i + p[i] > right:
center, right = i, i + p[i]
max_len, idx = max((v, i) for i, v in enumerate(p))
return s[(idx - max_len)//2 : (idx - max_len)//2 + max_len]
暴力破解法虽然简单易懂,但是在实际应用中效率较低。中心扩展法能够较快地找到最长回文子串,但是需要考虑回文串长度奇偶性的问题。马拉车算法是目前最优解,时间复杂度为O(n),但是实现起来较为复杂,需要仔细考虑各种细节问题。