zoukankan      html  css  js  c++  java
  • poj 3693 后缀数组 重复次数最多的连续重复子串

    Maximum repetition substring
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 10612   Accepted: 3277

    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

    题意:
    给定一个字符串,求重复次数最多的连续重复子串。输出字典序最小的。
    代码:
    //论文题,还是挺难的。连续出现1次是肯定的,我们枚举重复部分的长度L,把然后把字符串分成长为L的若干段,s[0],s[L],s[2*L]...
    //那么要求的子串必然会包含相邻的两段,所以看s[i*L]和s[i*L+L]向前和向后能匹配多远(i*L~i*L+L是其中的一部分),即求出来他们
    //的lcp,向后最远最多是lcp的终点,向前我们可以给他向前枚举L长度个单位(没必要枚举超过L,前一段计算包含了)看看最多能匹
    //配多少,还要保持字典序最小。
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int MAXN=200000;
    int sa[MAXN+9],he[MAXN+9],ra[MAXN+9],xx[MAXN+9],yy[MAXN+9],buc[MAXN+9],f[MAXN+9][30];
    char s[MAXN+9];
    int len,m;
    void get_suf()
    {
        int *x=xx,*y=yy;
        for(int i=0;i<m;i++) buc[i]=0;
        for(int i=0;i<len;i++) buc[x[i]=s[i]]++;
        for(int i=1;i<m;i++) buc[i]+=buc[i-1];
        for(int i=len-1;i>=0;i--) sa[--buc[x[i]]]=i;
        for(int k=1;k<=len;k<<=1){
            int p=0;
            for(int i=len-1;i>=len-k;i--) y[p++]=i;
            for(int i=0;i<len;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
            for(int i=0;i<m;i++) buc[i]=0;
            for(int i=0;i<len;i++) buc[x[y[i]]]++;
            for(int i=1;i<m;i++) buc[i]+=buc[i-1];
            for(int i=len-1;i>=0;i--) sa[--buc[x[y[i]]]]=y[i];
            swap(x,y);
            p=1;x[sa[0]]=0;
            for(int i=1;i<len;i++){
                if(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k])
                    x[sa[i]]=p-1;
                else x[sa[i]]=p++;
            }
            if(p>=len) break;
            m=p;
        }
        for(int i=0;i<len;i++) ra[sa[i]]=i;
        int k=0;
        for(int i=0;i<len;i++){
            if(ra[i]==0) { he[0]=0; continue; }
            if(k) k--;
            int j=sa[ra[i]-1];
            while(s[i+k]==s[j+k]&&i+k<len&&j+k<len) k++;
            he[ra[i]]=k;
        }
    }
    void rmq1()
    {
        he[0]=he[len]=0;
        for(int i=0;i<=len;i++) f[i][0]=he[i];
        for(int j=1;(1<<j)<=len;j++){
            for(int i=0;i+(1<<j)-1<=len;i++)
                f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
        }
    }
    int rmq2(int ql,int qr)
    {
        if(ql>qr) swap(ql,qr);
        ql++;
        int k=0;
        while(1<<(k+1)<=qr-ql+1) k++;
        return min(f[ql][k],f[qr-(1<<k)+1][k]);
    }
    void solve(int &st,int &ed,int ans)
    {
        for(int l=1;l*2<=len;l++){
            for(int i=0;i+l<len;i+=l){
                if(s[i]!=s[i+l]) continue;
                int ll=rmq2(ra[i],ra[i+l]);
                for(int j=0;j<=l;j++){
                    int ii=i-j;
                    if(ii<0||s[ii]!=s[ii+l]) break;
                    int num=(j+ll)/l+1;
                    if(num>ans||(num==ans&&ra[st]>ra[ii])){
                        ans=num;
                        st=ii;ed=st+ans*l-1;
                    }
                }
            }
        }
    }
    int main()
    {
        int cas=0;
        while(scanf("%s",s)&&s[0]!='#'){
            len=strlen(s);
            m=200;
            get_suf();
            rmq1();
            int st=sa[0],ed=sa[0];
            solve(st,ed,1);
            printf("Case %d: ",++cas);
            for(int i=st;i<=ed;i++) printf("%c",s[i]);
            printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    [再寄小读者之数学篇](2014-07-17 一阶中值)
    对流体力学做出巨大贡献的杰出历史人物
    理科生毁灭世界
    [再寄小读者之数学篇](2014-07-17 行列式的计算)
    [再寄小读者之数学篇](2014-07-16 高阶导数的一个表达式)
    [再寄小读者之数学篇](2014-07-16 与对数有关的不等式)
    [再寄小读者之数学篇](2014-07-16 凹函数与次线性性)
    [再寄小读者之数学篇](2014-07-16 二阶中值)
    [再寄小读者之数学篇](2014-07-16 任意阶导数在零处为零的一个充分条件)
    对PostgreSQL xmin的深入学习
  • 原文地址:https://www.cnblogs.com/--ZHIYUAN/p/7617920.html
Copyright © 2011-2022 走看看