HDU 3068最长回文串

 
//#include <fstream>
#include <iostream>
using namespace std;
#define Max 110005
#define inf 10000000
//#define DUG_MEME 0
char a[Max];//主串
char b[Max];//模式串
int nextb[Max],nexta1[Max],nexta2[Max],ans;
void kmp1(char *b,int *nextb){
    int i,j,k,t;
    i=0;
    while(b[i]==b[i+1])i++;
    nextb[1]=i;
    k=1;
    for(i=2;b[i];i++){
        if(nextb[i-k]+i<nextb[k]+k)nextb[i]=nextb[i-k];
        else{
            j=nextb[k]+k-i;
            if(j<0)j=0;
            while(b[j]==b[j+i]&&b[i+j])j++;
            nextb[i]=j;
            k=i;
        }
    }
}
void kmp2(char *a,char *b,int *nexta,int *nextb,int len)
{
    kmp1(b,nextb);
#ifdef DUG_MEME
    for(int i = 0; i < 10; i++) cout << nextb[i] << " ";
    cout << endl;
#endif
    int i,j,k;
    i=0;
    while(a[i]==b[i])i++;
    nexta[0]=i;
    k=0;
    for(i=1;i<len;i++)
    {
        if(nextb[i-k]+i<nexta[k]+k)nexta[i]=nextb[i-k];
        else
        {
            j=nexta[k]+k-i;
            if(j<0)j=0;
            while(b[j]==a[j+i]&&b[j]&&j+i<len)j++;
            nexta[i]=j;
            k=i;
        }
    }
}
void rev(char *a,int len)
{
    char t;
    for(int i=0;i<len/2;i++)t=a[i],a[i]=a[len-1-i],a[len-1-i]=t;
}
void solve(char *a,int len)
{
    if(len<=ans||len<2)return ;
    int mid=len>>1;
    int i;
    for(i=mid;i<len;i++) b[i-mid]=a[i];//b[0...mid - 1] = a[mid....len - 1] 
    b[i-mid]=0;//b[mid] = '0';
    rev(a,len);//反转字符串
    kmp2(a,b,nexta1,nextb,len);
    rev(a,len);
    for(i=0;i<mid;i++) b[i]=a[mid-i-1];
    b[i]=0;
    kmp2(a,b,nexta2,nextb,len);
    nexta1[len]=nexta2[len]=0;
    for(i=0;i<mid;i++)
    {
        if(nexta2[i]>=(mid-i)/2)
        {
            int x=mid-i+2*nexta1[len-i];
            if(x>ans)ans=x;
        }
    }
    // (1)
    // ABCDEEDC
    // a CDEEDCBA
    // b EEDC
    // nextb  01000000
    // nexta1 00410000
    //(2)
    // a ABCDEEDC
    // b DCBA
    // nextb  00000000
    // nexta2 00010020
    for(i=mid;i<len;i++)
    {
        if(nexta1[len-i]>=(i-mid)/2)
        {
            int x=i-mid+2*nexta2[i];
            if(x>ans)ans=x;
        }
    }
    solve(a, mid-1);
    solve(a + mid, len-mid);
}
int main()
{
    //freopen("cin.txt","r",stdin);
    while(scanf("%s",a)!=EOF)
    //std::ifstream cin("c:\\cin.txt");
    //while (cin >> a)
    {
    //for (int i = 0; i < 1000; ++i)
    {
        ans=1;
        solve(a,strlen(a));
        printf("%d\n",ans);
    }
    }
}



方法:后缀数组

你可能感兴趣的:(c)