Manacher算法--O(n)回文子串算法

马拉车算法详解地址

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int p[2000010];//记录以s[i]为中心的回文串最大可向右延伸几位,p[i]-1为原串以i为中心的最长回文串长度
int Find(string s)
{
    int mx=0,id=0;//mx记录向右延伸到的最大值,id记录最长回文串的中心下标
    memset(p,0,sizeof(p));
    int l=s.size();
    for(int i=1; i<l; i++)
    {
        if(mx>i)
            p[i]=min(p[2*id-i],mx-i);//j=2*id-i ;   id为i与j的对称点,当mx-i>p[j],i会延伸到和j一样,反之会延伸到和mx-i一样
        else
            p[i]=1;
        while(s[i-p[i]]==s[i+p[i]])//一个一个往后匹配相同长度加1
            p[i]++;
        if(i+p[i]>mx)//更新mx和id
        {
            mx=i+p[i];
            id=i;
        }
    }
    for(int i=0; i<l; i++)
        if(i+p[i]==l)//找到可延伸到原串最后的最长回文串,返回长度
            return p[i]-1;
}
int main()
{
    int ncase,Z=0;
    scanf("%d",&ncase);
    while(ncase--)
    {
        string str,x;
        x+='$';//防止while判断越界
        x+='#';
        cin>>str;
        int l=str.size();
        for(int i=0; i<l; i++)//解决奇偶回文串,全变为奇数
        {
            x+=str[i];
            x+='#';
        }
        //如果用char记得在最后加反斜杠0
        printf("Case %d: %d\n",++Z,l-Find(x)+l);//差值为需要加多少达到回文串,加长度为加之后的回文串长度
    }
}
发布了110 篇原创文章 · 获赞 18 · 访问量 3万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章