关于最大回文子串问题,有两种处理方法:
1.以每个字符为中心,向两边寻找回文子串,遍历整个数组后,返回最长的。
该方法时间复杂度较大为o(n^2)
2.一个中等难度的动态规划算法:马拉车
step1:给每个字符左右都加上特殊字符比如'#',处理后,能使字符串s长度为奇
step2:现在的问题变成如何高效求得RL数组
定义:RL:是一个回文半径数组
RL[i]:以第i个字符为对称轴的回文半径
maxRight:当前访问到的所有回文串中最右边的字符位置
Pos:maxRight对应回文串的对称轴所在位置
i:第i个字符
j:i关于pos的对称点
(1):i在maxright右边:就是说以i为对称轴的回文串还没被访问。
这时,以i为中心向两边扩展,当达到边界or字符不相等时停止。
(2):i在maxright左边:扫到了一部分以i为对称轴的子串。
这时,令以i为对称轴的回文半径RL【i】=min(RL[j],maxright-i)
然后再以i为中心向两边扩展,直到左!=右且到达边界
最后更新maxright=max(maxright,RL[i]+i-1)且若maxright变,Pos会变为Pos=i
很抽象,上代码:
# -*- coding:utf-8 -*- #@author:xinxinzhang def manacher(s): s='#'+'#'.join(s)+'#'#step1 RL=[0]*len(s) #各种初始化一下,RL是回文半径数组 MaxRight=0 Pos=0 Maxlen=0 for i in range(len(s)): if i<MaxRight:#i在maxright左边 RL[i]=min(RL[2*Pos-i],MaxRight-i) else: #i在maxright右边,以i为中心的回文串还没扫到,此时,以i为中心向两边扩展 RL[i]=1#RL=1:只有自己 #以i为中心扩展,直到左!=右or达到边界(先判断边界) while i-RL[i]>=0 and i+RL[i]<len(s) and s[i-RL[i]]==s[i+RL[i]]: RL[i]+=1 #更新Maxright pos: if RL[i]+i-1>MaxRight: MaxRight=RL[i]+i-1 Pos=i #更新最长回文子串的长; Maxlen=max(Maxlen,RL[i]) s=s[RL.index(Maxlen)-(Maxlen-1):RL.index(Maxlen)+(Maxlen-1)] s=s.replace('#','') return s print(manacher('cbbd'))
来源:CSDN
作者:zuanfengxiao
链接:https://blog.csdn.net/zuanfengxiao/article/details/80341483