manacher(马拉车算法)过程及python代码实现
问题应用
回文子串的寻找
回文串特点
奇回文:aba
偶回文:abba
变量定义
mx:所有已知右边界中最靠右的位置
id:mx对应的中心点
p[]:以当前index为中心,s'回文的最大半径,p[i]-1的值就是s中以i为中心回文的长度
算法过程
1. 字符串处理
把所有的回文处理成奇回文,即在字符中间插入字符串中没有的一个字符(本文加的是#)输入:s 处理后:s'
2. 核心过程
变量初始化
mx = -1
id = -1
从头遍历s',i为坐标
p[i]的先置过程:
若i<mx:说明i之前已经遍历过了
p[i]值得设定(这一步省了很多工作)
p[i] = min(mx-i,p[2id-i])其中,p[2id-i]为i相对于id的对称位
若mx>p[2id-i],因为以2id-i为中心的回文也在当前回文内,以i为中心的回文的半径至少也等于p[2id-i],至于以i为中心的回文在不在mx以外,由后面去检查
若mx<p[2id-i],说明以2id-i为中心的回文已经超过了当前以id为中心的回文外,则至少在以id为中心的回文内(mx-i)以i为中心的回文是回文
若i>mx:则置p[i]=1
(以上是p[i]的先置过程)
p[i]的增加过程:
循环判断s'[i-p[i]] == s'[i+p[i]],p[i]+1,直至不等为止(注意判断s'数组是否越界,即i-p[i]与i+p[i]是否越界)
如果p[i]+i > mx,则更新mx和id值
这样,p[]全部处理完毕,即找出s中所有回文串及其长度
python代码
class Solution: def init0(self,s):#预处理s r = "#".join(s) r = list(r) r.append("#") r.insert(0,"#") return r def manacher(self,s): mx = -1 id0 = -1 max_length = -1 rIndex = -1 s = self.init0(s) p =[-1 for i in range(len(s))] print(s) for i in range(1,len(s)-1): if i < mx: p[i] = min(mx-i,p[2*id0-i]) else: p[i] = 1 while i >= p[i] and i+p[i]<len(p) and s[i-p[i]] == s[i+p[i]]: p[i] += 1 if mx < i + p[i]: mx = i + p[i] id0 = i if p[i]-1 > max_length: rIndex = i max_length = p[i]-1 tmp = s[rIndex-p[rIndex]+1:rIndex+p[rIndex]] return "".join("".join(tmp).split("#")) s = Solution() print(s.manacher("ababd"))