Manacher 算法模板

来源:互联网 发布:股票盈亏软件 编辑:程序博客网 时间:2024/05/22 10:53


参考自 http://www.cnblogs.com/ikids/articles/4660011.html

http://blog.csdn.net/ggggiqnypgjg/article/details/6645824/

算法大致过程是这样。先在每两个相邻字符中间插入一个分隔符,当然这个分隔符要在原串中没有出现过。一般可以用‘#’分隔。这样就非常巧妙的将奇数长度回文串与偶数长度回文串统一起来考虑了(见下面的一个例子,回文串长度全为奇数了),然后用一个辅助数组P记录以每个字符为中心的最长回文串的信息。Pid]记录的是以字符strid]为中心的最长回文串,当以strid]为第一个字符,这个最长回文串向右延伸了Pid]个字符。

关键的代码

if( mx > i)
    p[i]=MIN( p[2*id-i], mx-i);

就是当前面比较的最远长度mx>i的时候,Pi]有一个最小值。这个算法的核心思想就在这里,为什么P数组满足这样一个性质呢?
   (下面的部分为图片形式)


模板

/* *对于n长度的字符串,存储是从1~n+n+1, 实际长度是n+n+2; *注意size范围 */const int SIZE =  3000;char  s[SIZE];int p[SIZE];void manacher() //manacher 函数{    int len=strlen(s);    for(int i=len;i>=0;--i) //将s扩大,中间加#,开头加*    {        s[i+i+2]=s[i];        s[i+i+1]='#';    }    s[0]='*';    int id,mx=0;  //mx代表以id为中心时,到达最远的位置    for(int i=1;i<=len+len+1;++i)    {        if(mx>i) p[i]=min(p[2*id-i],mx-i); //如果到达最远位置大于当前匹配的地方,则p[i]取min(id的对称点的p,到达最远距离-i)        else p[i]=1; //如果i在mx右方,则p[i]=-1;        while(s[i-p[i]] == s[i+p[i]])++p[i];   //判断i回文长度        if(i+p[i]>mx) //看是否要更新最远距离,如果要,将此点作为中心。        {            id=i;            mx=p[i]+i;        }    }}



0 0
原创粉丝点击