美文网首页DataStructure
Manacher算法「最长回文字符串」

Manacher算法「最长回文字符串」

作者: 雨落八千里 | 来源:发表于2019-09-27 00:11 被阅读0次

Manacher算法原理

  • 最长回文字符串包括奇数长的和偶数长的,求的时候都要分情讨论,Manacher算法做了一个简单的处理,很巧妙地把奇数长度回文串与偶数长度回文串统一考虑,也就是在每个相邻的字符之间插入一个分隔符,串的首尾也要加,当然这个分隔符不能再原串中出现,一般可以用‘#’字符。
    这样一来,原来的奇数长度回文串还是奇数长度,偶数长度的也变成以‘#’为中心奇数回文串了。
    其次给每个字符串首部加一个题目中不会出现的字符,避免处理越界问题。(一般加’$’)


    如图字符串S就是通过Manacher算法预处理得到的新串
    P数组记录的以 S[i]为中间S字符的回文串向右能匹配的最大长度(包括S[i]这个字符).
    S[i]不是所加字符‘#’时,P[i]-1就是字符串长度了
  • 假设以i为中心的回文串长度为len,因为p[ i]记录以 S[i]为中间字符的回文串向右能匹配的长度,所以有
    len=2*p[ i ]-1;
    又因为此时串中加了其他字符#,以s[i]为中心的回文串一定是以#开头和结尾的,以#为中间字符的就是长度为偶数的,以非#号为中间字符的就是长度为奇数的,例如“#b#b#”“#b#a#b#”所以减去最前或者最后的‘#’字符就是原串中长度的2倍,即原串长度为(S-1)/2,化简的P[i]-1

Manacher算法实现

  • Manacher算法实现就是要找出p数组,如何找出P数组是关键.

首先从左往右依次计算P[i],当计算P[i]时,P[j](0<=j<i)已经计算完毕。设mx为之前计算中最长回文子串的右端点的最大值,并且设取得这个最大值的位置为id,分两种情况:

情况1:

  1. i<=mx
    那么找到i相对于id的对称位置,设为j,那么如果p[j]<mx-i
    因为i+j=2*id,j能向左匹配的最左端点的坐标是j-p[j]+1
    所以可知p[j]+2*id<mx+j,所以可知2*id-mx<j-p[j]+1
    向如下图:

    那么说明以j为中心的回文串一定在以id为中心的回文串的内部,且ji关于位置id对称,那么意味着以S[i]为中间字符的回文串能向右匹配最右端点没有超过mx。由回文串的定义可知,一个回文串反过来还是一个回文串,所以以i为中心的回文串的长度至少和以j为中心的回文串一样,所以P[i]=P[j]
  2. 如果P[j]>=mx-i,由对称性,说明以i为中心的回文串可能会延伸到mx之外,而大于mx的部分我们还没有进行匹配,所以要从mx+1位置开始一个一个进行匹配,直到发生失配,从而更新mx和对应的id以及P[i]

    虽然p[j]>mx-i,但是可以保证的是i<->mx这一段是跟2*id-mx<->j是一样的,说明以s[i]为中心的回文串至少有mx-i这么长

情况2:
i>mx
如果i比mx还要大,说明对于中点为i的回文串还一点都没有匹配,这个时候,就只能老老实实地一个一个匹配了,匹配完成后要更新mx的位置和对应的id以及P[i]


        int len=strlen(s);
        int mx=0;
        int id=0;
        int res=-1;
        for(int i=len;i>=0;i--)
        {
            s[i*2+2]=s[i];
            s[i*2+1]='#';
        }
        s[0]='$';//加上特殊字符防止越界
        for(int i=0;i<=2*len+1;i++)
        {
            if(mx>i)//mx<i的情况
            {
                p[i]=min(p[2*id-i],mx-i);//比较p[j]大还是mx-i大,取小的
            }
            else//如果i>=mx,要从头开始匹配
            {
                p[i]=1;
            }
            while(s[i-p[i]]==s[i+p[i]])//一个一个比较
            {
                p[i]++;
            }
            if(p[i]+i>mx))//若新计算的回文串右端点位置大于mx,要更新id和mx的值

            {
                mx=p[i]+i;
                id=i;
            }
            res=max(res,p[i]-1);
        }

相关文章

  • 最长回文子串

    最长回文子串——Manacher 算法 1. 问题定义 最长回文字符串问题:给定一个字符串,求它的最长回文子串长度...

  • Manacher's Algorithm算法分析Java

    Manacher's Algorithm俗称马拉车算法,对于求字符串中最长回文子串效率极高。 在求最长回文子串的时...

  • Manacher's Algorithm 的理解

    在 leetcode 刷题刷到求字符串的最长回文字串,而马拉车算法(Manacher's Algorithm), ...

  • Manacher's algorithm

    Manacher算法主要解决的问题是求给定字符串中最长的回文字符串。 以前咱们求解回文字符串的步骤是找中心点, ...

  • Manacher算法

    前言 Manacher算法用于求解字符串中最长的回文子串,它和KMP算法的改进方式很类似,都是基于暴力求解的方法,...

  • 经典算法问题:最长回文子串之 Manacher 算法

    title: 经典算法问题:最长回文子串之 Manacher 算法date: 2019-02-17 08:00:0...

  • Manacher算法「最长回文字符串」

    算法原理最长回文字符串包括奇数长的和偶数长的,求的时候都要分情讨论,Manacher算法做了一个简单的处理,很巧妙...

  • 一文弄懂Manacher算法

    今天我们来介绍一下处理回文字符串的算法:Manacher(俗称“马拉车”)。 算法功能 回文字符串的通俗定义是:如...

  • Manacher算法详解

    目录结构如下: 引入 Manacher算法详解 例题 References 1. 问题引入 最长回文子串(Long...

  • hdu 3068 Manacher

    hdu 3068求一个字符串的最长回文长度。套用Manacher模板即可。

网友评论

    本文标题:Manacher算法「最长回文字符串」

    本文链接:https://www.haomeiwen.com/subject/fhmnyctx.html