zoukankan      html  css  js  c++  java
  • URAL

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

    思路:(这道题其实是可以用马拉车算法的而且复杂度很优秀 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]='';
            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
    */
  • 相关阅读:
    电脑发朋友圈神器?不是严格意义上的
    微信公众平台投票功能升级 可多渠道发布投票
    多客服功能终于也向所有微信认证的订阅号开放了
    微信电脑版-微信for windows客户端发布
    微信朋友圈广告的赢家是他们
    微信公众平台原创声明功能公测 自媒体原创保护的福音
    微信公众平台数据接口正式对所有认证公众号开放
    壕,微信6.1版发微信红包更方便了,我们去喝杯茶吧
    微信公开课发布微信官方教程:教你用好微信JS-SDK接口
    微信公众平台开放JS-SDK(微信内网页开发工具包)
  • 原文地址:https://www.cnblogs.com/lalalatianlalu/p/9515797.html
Copyright © 2011-2022 走看看