• SPOJ:REPEATS


    http://www.spoj.com/problems/REPEATS/

      求重复次数最多的连续重复子串。

      论文题。枚举子串长度L,重复一次是肯定的,我们考虑至少重复两次的情况。那么在1,L+1,2L+1...kL+1这些位置一定会覆盖至少连续的两个。于是我们枚举连续的两个位置,向前向后匹配,匹配总长/L+1即为重复次数。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=50015;
    int n,len;char s[maxn<<1];
    struct Tsuffix_array{
        static const int maxn=::maxn<<1;
        int sum[maxn],sa[maxn],rank[maxn],tsa[maxn],trank[maxn];
        bool cmp(int i,int j,int l){
            if (i+l>len||j+l>len) return 0;
            return rank[i]==rank[j]&&rank[i+l]==rank[j+l];
        }
        void suffix_sort(){
            int m=255,p,i,j;
            for (i=0;i<=m;++i) sum[i]=0;
            for (i=1;i<=len;++i) ++sum[rank[i]=s[i]];
            for (i=1;i<=m;++i) sum[i]+=sum[i-1];
            for (i=len;i>=1;--i) sa[sum[rank[i]]--]=i;
            for (p=0,j=1;p<len;j<<=1,m=p){
                for (p=0,i=len-j+1;i<=len;++i) tsa[++p]=i;
                for (i=1;i<=len;++i) if (sa[i]>j) tsa[++p]=sa[i]-j;
                for (i=0;i<=m;++i) sum[i]=0;
                for (i=1;i<=len;++i) ++sum[rank[tsa[i]]];
                for (i=1;i<=m;++i) sum[i]+=sum[i-1];
                for (i=len;i>=1;--i) sa[sum[rank[tsa[i]]]--]=tsa[i];
                for (p=trank[sa[1]]=1,i=2;i<=len;++i) trank[sa[i]]=cmp(sa[i],sa[i-1],j)?p:++p;
                memcpy(rank,trank,sizeof(int)*(len+1));
            }
        }
        static const int maxk=20;
        int height[maxn],fmn[maxk][maxn];
        void get_height(){
            for (int h=0,i=1;i<=len;++i){
                if (rank[i]==1) continue;
                for (h?--h:0;s[i+h]==s[sa[rank[i]-1]+h];++h);
                height[rank[i]]=h;
            }
            for (int i=2;i<=len;++i) fmn[0][i]=height[i];
            for (int k=1;k<maxk;++k)
                for (int i=1<<k;i<=len;++i)
                    fmn[k][i]=min(fmn[k-1][i],fmn[k-1][i-(1<<(k-1))]);
        }
        int LCP(int x,int y){
            if (x>y) swap(x,y);
            int k=log2(y-(++x)+1);
            return min(fmn[k][y],fmn[k][x+(1<<k)-1]);
        }
        int check(int l){
            int res=0;
            for (int i=1,j=l+1;j<=n;i=j,j=i+l){
                int Rmatch=LCP(rank[i],rank[j]);
                int Lmatch=LCP(rank[n+1+(n-i+1)],rank[n+1+(n-j+1)]);
                res=max(res,(Lmatch+Rmatch-1)/l+1);
            }
            return res;
        }
    }SA;
    void init(){
        scanf("%d",&n);s[n+1]=1;len=(n<<1)+1;s[len+1]=0;
        for (int i=1;i<=n;++i){char c[2];scanf("%s",c);s[i]=c[0];}
        for (int i=1;i<=n;++i) s[n+1+(n-i+1)]=s[i];
    }
    void work(){
        SA.suffix_sort();
        SA.get_height();
        int res=1;
        for (int i=1;i<=n/2;++i) res=max(res,SA.check(i));
        printf("%d
    ",res);
    }
    int main(){
        int cases;scanf("%d",&cases);
        while (cases--){init();work();}
        return 0;
    }
    my code
  • 相关阅读:
    [已读]精通AngularJS
    [在读]HTML5数据推送应用开发
    [未读]深入浅出node.js
    [已读]用Angularjs开发下一代web应用
    [在读]Secrets of the javascript Ninja
    Element ui select同时获取value和label的值
    Element ui tree树形控件获取父节点id
    Element ui tree结合Vue使用遇到的一些问题(一)
    vue数组检测更新问题
    css3实现流星坠落效果
  • 原文地址:https://www.cnblogs.com/iamCYY/p/4738363.html
Copyright © 2020-2023  润新知