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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章