📅  最后修改于: 2023-12-03 15:32:48.457000             🧑  作者: Mango
回文子串指的是正反读都一样的字符串,如“level”,“noon”等。在字符串处理中,寻找最长回文子串是一个经典问题,也是一个非常有趣的问题。本文将介绍Manacher算法,该算法可以在线性时间内求解最长回文子串。
Manacher算法是一种基于对称性的思想,该算法在处理每个字符时,先找到以当前字符为对称中心的最长回文子串半径,然后继续向后遍历字符串。通过维护一个“右边界”和“对称中心”两个变量,可以以线性时间复杂度完成遍历。
设字符串为s,s长度为n,回文子串的长度为len,对称中心为mid。算法具体流程如下:
构造新字符串t:在s中每个字符之间添加特殊字符“#”,并在s的开头和结尾添加字符“$”和“%”,用于避免越界。例如,字符串s=“ABB”转换为字符串t=“$#A#B#B#%”。
初始化数组P:P[i]代表以t[i]为对称中心的最长回文子串的半径长度。
初始化变量mid和right:mid表示已经求得的最长回文子串的对称中心,right表示mid对应的最长回文子串的右边界。
遍历字符串t:从左到右遍历t数组,对于每个字符t[i],先判断i是否在已经求得的最长回文子串的右边界之内。如果i在最长回文子串的右边界之内,则将P[i]的初值设为P[mid-(i-mid)](即t[i]关于mid的对称位置的回文半径),同时扩展P[i]的范围(向左右两边扩展),直至不能扩展为止。如果i在最长回文子串的右边界之外,就以t[i]为中心,向外扩展找最长回文子串,并更新mid和right的值。
遍历P:在P数组中找到最大值,其即为最长回文子串的长度。
通过最长回文子串的长度和对称中心mid,可以求得最长回文子串在s中的位置和具体内容。
下面是Python语言实现Manacher算法的代码片段(以字符串s=“babad”为例):
# 构造新字符串t
t = '$#' + '#'.join(list(s)) + '#%'
n = len(t)
# 初始化数组P
P = [0] * n
# 初始化中心点和右边界
mid, right = 0, 0
for i in range(1, n-1):
if i < right:
P[i] = min(P[mid-(i-mid)], right-i)
while t[i-P[i]-1] == t[i+P[i]+1]:
P[i] += 1
if i + P[i] > right:
mid, right = i, i + P[i]
# 找到最长回文子串的长度
max_len, max_mid = max((P[i], i) for i in range(1, n-1))
# 求得最长回文子串
start = (max_mid - max_len) // 2
end = start + max_len - 1
longest_palindrome = s[start:end+1]
Manacher算法通过对称性的思想,以线性时间复杂度解决了最长回文子串的求解问题,是字符串处理中非常经典和有趣的问题。掌握了Manacher算法,可以为字符串处理类问题提供有效的思路和解决方法。