URAL - 1297 Palindrome (后缀数组)

题意:就是给你一个字符串,然后求出他的最大回文串,然后打印字符串

思路:(这道题其实是可以用马拉车算法的而且复杂度很优秀 On的)但这里用的是后缀数组的解法,我们把一个串reverse翻转贴在后面,然后就是枚举中点,然后向两边扩展的,向两边扩展是可以用lcp做的,(NOI 2016中也用到了类似了方法)然后就可以 愉快地搬运了(ps:中间出了一点bug,找了很久才找到)

AC代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL read()
{
    LL x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

const int maxn=1e4+7;
char s[maxn];
int T,n,Log[maxn],l,r,f[maxn],g[maxn];
void init_suffix()
{
    for(int i=2;i<maxn;i++)Log[i]=Log[i>>1]+1;
}
struct SuffixArray
{
    char s[maxn*2];
    int sa[maxn*2],rk[maxn*2],height[maxn*2],tmp[maxn*2],cnt[maxn*2],f[15][maxn*2],len;
    inline void init()
    {
        for(int i=0;i<len*2+5;i++)s[i]=0;
    }
    inline void suffix(int m)
    {
        int i,j,k,len1=len+1;;
        for(i=0;i<len1*2+5;i++)rk[i]=sa[i]=height[i]=tmp[i]=0;
        for(i=0;i<m;i++)cnt[i]=0;
        for(i=0;i<len1;i++)cnt[rk[i]=s[i]]++;
        for(i=1;i<m;i++)cnt[i]+=cnt[i-1];
        for(i=0;i<len1;i++)sa[--cnt[rk[i]]]=i;
        for(k=1;k<=len1;k<<=1){
            for(i=0;i<len1;i++){
                j=sa[i]-k;
                if(j<0)j+=len1;
                tmp[cnt[rk[j]]++]=j;
            }
            sa[tmp[cnt[0]=0]]=j=0;
            for(i=1;i<len1;i++){
                if(rk[tmp[i]]!=rk[tmp[i-1]]||rk[tmp[i]+k]!=rk[tmp[i-1]+k])cnt[++j]=i;
                sa[tmp[i]]=j;
            }
            memcpy(rk,sa,len1*sizeof(int));
            memcpy(sa,tmp,len1*sizeof(int));
            if(j>=len1-1)break;
        }
//        for(j=rk[height[i=k=0]=0];i<=len;i++,k++){
//            while(~k&&s[i]!=s[sa[j-1]+k])height[j]=k--,j=rk[sa[j]+1];
//        }
        k=0;
        for(i=0;i<=len;i++) rk[sa[i]]=i;
        for(i=0;i<len;i++) {
            if(k) k--;
            j=sa[rk[i]-1];
            while(s[j+k]==s[i+k]) k++;
            height[rk[i]]=k;
        }
    }
    inline void build()
    {
        int i,j;
        for(i=1;i<=len;i++)f[0][i]=height[i];
        for(j=1;j<15;j++){
            for(i=1;i+(1<<j-1)<=len;i++){
                f[j][i]=min(f[j-1][i],f[j-1][i+(1<<j-1)]);
            }
        }
    }
    inline int ask(int x,int y)
    {
        int k=Log[y-x+1];
        return min(f[k][x],f[k][y-(1<<k)+1]);
    }
    inline int lcp(int x,int y)
    {
        x=rk[x],y=rk[y];
        if(x>y)swap(x,y);
        return ask(x+1,y);
    }
}A;
inline int lcp(int x,int y){return A.lcp(x-1,y-1);}
int main()
{
    init_suffix();
    while(~scanf("%s",s)){
        int n=strlen(s);
        A.len=2*n+2;
        A.init();
        for(int i=0;i<n;i++){
            A.s[i]=s[i];
        }
        A.s[n]='#';
        for(int i=n+1,j=n-1;i<2*n+1;i++,j--){
            A.s[i]=s[j];
        }
        A.s[2*n+1]='\0';
        A.suffix(128);
        A.build();
        int len=2*n+1;
        int ans=1,k=0;
        for(int i=1;i<n;i++){
            if(2*A.lcp(i+1,len-i)+1>ans)ans=2*A.lcp(i+1,len-i)+1,k=i-A.lcp(i+1,len-i);
            if(2*A.lcp(i,len-i)>ans)ans=2*A.lcp(i,len-i),k=i-A.lcp(i,len-i);
        }
        for(int i=k;i<k+ans;i++)
            printf("%c",s[i]);
        puts("");
    }
    return 0;
}
/*
Kazak
*/

 

posted @ 2018-08-22 09:30  啦啦啦天啦噜  阅读(210)  评论(0编辑  收藏  举报