Manacher算法

用于查找一个字符串的最长回文子串的线性算法

 

p[i]:以i为中心的回文串半径

从前往后扫,当扫到p[i]时已计算了p[1~i-1]

记录i+k前所有回文串中能延伸到的最右端位置,即p[i]+i

计算p[i+k]:

  1. i+k不在前面任何回文串中(maxlen<i+k)

      则初始化p[i+k]=1,然后向左右延伸

  2. i+k被前面以i为中心的回文串包含(maxlen>i+k)

      则i+k与i-k关于i对称,分三种情况:

        ① i-k回文串有一部分在i的回文串之外,则p[i+k]=p[i]-k

        ② i-k回文串全部在i的回文串内,则p[i+k]=p[i-k]

        ③ i-k回文串与i回文串左端重合,则p[i+k]=p[i-k],且可能继续增加,向左右延伸

    

 

 

    总结: p[i+k]=min(p[i-k],p[i]-k)

        while(s[i+k-p[i+k]]==s[i+k+p[i+k]]) ++p[i+k]

    Tip: ·偶数长度的字符串中心为空,则在字符串中加入‘#

        如 abab --> #a#b#a#b#

       ·最长回文子串长度为maxlen-1

          ans = [(maxlen-2)*2]/2+1 = maxlen-1

            (-2):去掉左端#和中心字符

            (*2):对称

            (/2):#与字符数量相等

            (+1):加上中心字符

       ·令s[0]=‘*,因为首尾s[0]和s[2*len+2]要插入不同的字 符,防止p[i]越界

     

 

 

 

 

posted @ 2022-09-12 19:19  weimie  阅读(36)  评论(0)    收藏  举报