zoukankan      html  css  js  c++  java
  • poj3693 Maximum repetition substring

    Maximum repetition substring
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 9757   Accepted: 3004

    Description

    The repetition number of a string is defined as the maximum number R such that the string can be partitioned into R same consecutive substrings. For example, the repetition number of "ababab" is 3 and "ababa" is 1.

    Given a string containing lowercase letters, you are to find a substring of it with maximum repetition number.

    Input

    The input consists of multiple test cases. Each test case contains exactly one line, which
    gives a non-empty string consisting of lowercase letters. The length of the string will not be greater than 100,000.

    The last test case is followed by a line containing a '#'.

    Output

    For each test case, print a line containing the test case number( beginning with 1) followed by the substring of maximum repetition number. If there are multiple substrings of maximum repetition number, print the lexicographically smallest one.

    Sample Input

    ccabababc
    daabbccaa
    #

    Sample Output

    Case 1: ababab
    Case 2: aa

    Source

    【题意】:

    给定一个串,长度<=10^5,求它重复次数最多的连续重复子串(输出字典序最小的那个)。

    例如ccabcabc,答案就是abcabc

    原理:

      按照L划分,因为相邻两个i之间隔着一个L,s[i*L]和s[(i+1)*L]必定是真正循环节的同一个位置。

      对于当前的L,i,i+1,x=s[i*L],y=s[(i+1)*L],找前找后,知道了最早能匹配到t0,最晚能匹配到t1,因为不知道当前的起始点是真正循环节的第几个点,所以我们要往前找L个点看看它们是不是真正的起始点。

                                                                        (转载自KonjakJuruo)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e5+10;
    int n,cas,c[N],h[N],sa[N],tsa[N],rank[N],trank[N];
    int log2[N],f[N][20];
    char s[N];
    void DA(int maxx=30){
        int p;
        for(int i=0;i<=maxx;i++) c[i]=0;
        for(int i=1;i<=n;i++) c[rank[i]=s[i]-'a'+1]++;
        for(int i=2;i<=maxx;i++) c[i]+=c[i-1];
        for(int i=n;i;i--) sa[c[rank[i]]--]=i;
        trank[sa[1]]=p=1;
        for(int i=2;i<=n;i++){
            if(rank[sa[i]]!=rank[sa[i-1]]) p++;
            trank[sa[i]]=p;
        }
        for(int i=1;i<=n;i++) rank[i]=trank[i];
        for(int k=1;p<n;k<<=1,maxx=p){
            p=0;
            for(int i=n-k+1;i<=n;i++) tsa[++p]=i;
            for(int i=1;i<=n;i++) if(sa[i]>k) tsa[++p]=sa[i]-k;
            for(int i=0;i<=maxx;i++) c[i]=0;
            for(int i=1;i<=n;i++) trank[i]=rank[tsa[i]];
            for(int i=1;i<=n;i++) c[trank[i]]++;
            for(int i=2;i<=maxx;i++) c[i]+=c[i-1];
            for(int i=n;i;i--) sa[c[trank[i]]--]=tsa[i];
            trank[sa[1]]=p=1;
            for(int i=2;i<=n;i++){
                if(rank[sa[i]]!=rank[sa[i-1]]||rank[sa[i]+k]!=rank[sa[i-1]+k]) p++;
                trank[sa[i]]=p;
            }
            for(int i=1;i<=n;i++) rank[i]=trank[i];
        }
        for(int i=1,k=0;i<=n;i++){
            int j=sa[rank[i]-1];
            while(s[i+k]==s[j+k]) k++;
            h[rank[i]]=k;if(k>0) k--;
        }
    }
    void RMQ(){
        for(int i=1;i<=n;i++) f[i][0]=h[i];
        for(int i=2;i<=n;i++) log2[i]=log2[i>>1]+1;
        for(int j=1;j<=log2[n];j++){
            for(int i=1;i+(1<<j)-1<=n;i++){
                f[i][j]=min(f[i][j-1],f[i+(1<<j-1)][j-1]);
            }
        }
    }
    int query(int l,int r){
        int a=rank[l],b=rank[r];
        if(a>b) swap(a,b);
        a++;
        int k=log2[b-a+1];
        return min(f[a][k],f[b-(1<<k)+1][k]);
    }
    int main(){
        while(scanf("%s",s+1)==1){
            n=strlen(s+1);
            if(n==1&&s[1]=='#') break;
            printf("Case %d: ",++cas);
            DA();RMQ(); 
            int t0=0,t1=0,al=0,ar=0,ans=0;
            int lim=n>>1;
            for(int L=1,x,y,z;L<=lim;L++){
                for(int i=0;L*(i+1)+1<=n;i++){
                    x=L*i+1;y=L*(i+1)+1;
                    if(s[x]!=s[y]) continue;
                    z=query(x,y);
                    t1=y+z-1;//直接找右端点 
                    t0=0;
                    for(int j=0;j<L;j++){//往左匹配,找左端点  
                        if(x-j<1||s[x-j]!=s[y-j]) break;
                        t0=x-j;
                        int now=(t1-t0+1)/L;
                        if(ans<now||(ans==now&&rank[t0]<rank[al])){
                            ans=now;
                            al=t0;
                            ar=t0+now*L-1;
                        }
                    }
                }
            }
            if(!ans) printf("%c
    ",s[sa[1]]);
            else{
                s[ar+1]=0;
                puts(s+al);
            }
        }
        return 0;
    }

    SPOJ687 - REPEATS代码:

    https://cn.vjudge.net/solution/8510050/JKe7clp2sGx9adDe8dgL 

  • 相关阅读:
    IDEA 2019.3 最新激活教程,有效期到 2089 年!
    【猫狗数据集】读取数据集的第二种方式
    【猫狗数据集】计算数据集的平均值和方差
    【colab pytorch】其它注意事项
    【colab pytorch】训练和测试常用模板代码
    【colab pytorch】数据预处理
    【colab pytorch】提取模型中的某一层
    【colab pytorch】模型权重初始化
    【猫狗数据集】使用预训练的resnet18模型
    【猫狗数据集】使用top1和top5准确率衡量模型
  • 原文地址:https://www.cnblogs.com/shenben/p/6594798.html
Copyright © 2011-2022 走看看