最大回文子串manacher算法python

亡梦爱人 提交于 2019-12-04 20:16:07

关于最大回文子串问题,有两种处理方法:
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'))




易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!