manacher(最大回文串算法+手写模板)

poj3976
题意:求每个串的最大回文串长度。
这是一份通过manache算法理解过后手动模拟的算法,纯手写,便于理解

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char ch[2000005];
int hui[2000005];
char ca[2000005];
int index=0;
    int ma=0;
void solve()
{
//其中p为中心位置,r对应的最右边界,仔细观察可以发现r-p即为p位置的最大回文长度
    int p=0,r=0;
    int len=strlen(ca);
    for(int i=0; i<len; i++)
    {
        ch[i*2]='#';
        ch[i*2+1]=ca[i];
    }
    ch[len*2]='#';
    ch[len*2+1]='\0';
    len=2*len+1;

    for(int i=0; i<len; i++)
    {
        if(i>=(r))//当要进行回文求解的i位置在r右边时,无任何优化,暴力匹配。
        {
            int k=i+1;
            int l=0;
            while((k<len)&&(2*i-k>=0)&&(ch[k]==ch[2*i-k]))
            {
                l++;
                k++;
            }
            p=i;
            r=l+i;
            if(l>ma)
                ma=l,index=i;
            hui[i]=l;
        }
        else//反之
        {
            if((i+hui[2*p-i])<(r))//若通过以p为对称中心i的对称点为2*p-i,若i-i+hui[2*p-i]都在r左边,肯定是匹配的。
            {
                hui[i]=hui[2*p-i];
            }
            else//否则要在求解,但有下面的优化
            {
            //注意这里的批配起始位置为r,起始已匹配成果长度为r-i-1;
                int k=r;
                int l=r-i-1;
                while((k<len)&&(2*i-k>=0)&&(ch[k]==ch[2*i-k]))
                    l++,k++;
                p=i;
                r=l+i;
                if(l>ma)
                    ma=l,index=i;
                hui[i]=l;
            }
        }
    }
}
int main()
{
    int icase=1;
    while(cin>>ca)
    {
        ma=0;
        if(strcmp(ca,"END")==0)break;
        memset(hui,0,sizeof hui);
        solve();
        int len=strlen(ch);
        cout<<"Case "<<icase++<<": "<<ma<<endl;
    }
    return 0;
}

再贴一份大神模板

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAXN=1100100;
char Ma[MAXN*2];
int Mp[MAXN*2];
void Manacher(char s[],int len)
{
    int l=0;
    Ma[l++]='$';
    Ma[l++]='#';
    for(int i=0;i<len;i++)
    {
        Ma[l++]=s[i];
        Ma[l++]='#';    
    }   
    Ma[l]=0;
    int mx=0,id=0;
    for(int i=0;i<l;i++)
    {
        Mp[i]=mx>i?min(Mp[2*id-i],mx-i):1;//寻找下一个需要判断的地方 
        while(Ma[i+Mp[i]]==Ma[i-Mp[i]])Mp[i]++;
        if(i+Mp[i]>mx)
        {
            mx=i+Mp[i];
            id=i;
        }
    }
} 
char s[MAXN];
int main()
{
    int count=0;
    while(scanf("%s",s)!=EOF)
    {
        if(strcmp("END",s)==0)break;
        count++;
        int len=strlen(s);
        Manacher(s,len);
        int ans=0;
        for(int i=0;i<2*len+2;i++)
        {
            ans=max(ans,Mp[i]-1);
        }
        printf("Case %d: ",count);
        printf("%d\n",ans);
    }
    return 0;
}
发布了45 篇原创文章 · 获赞 27 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章