zoukankan      html  css  js  c++  java
  • POJ3693Maximum repetition substring (循环节)(后缀数组+RMQ)

    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

    题意:

    求里面一段字符串,它的循环次数最多,如果有多个,输出最小字典序的一个。

    思路就不说了,老题,可以去看论文。但是至少需要知道循环节的性质(具体的去KMP那里去看),大概是这样:

     s1=x y z

     s2=   x y z。如果,s1=s2,且下面的x对应上面的y,下面的y对应上面的z,则x=y ,y=z,则x=y=z。那么他们(x,y,z)就是循环节,而且循环了4次,上面的xyz和下面的z。

    下面说一下我的bug。。。

    • 手写的swap居然WA了,写在头文件下面的东西找bug根本找不到啊。。。TT,找到的时候WA的一声就哭出来了。
    //应该是因为疑惑运算超过int了
    int min(int a,int b)  { if(a<b) return a;return b;}
    void swap(int a,int b) {a^=b;b^=a;a^=b;} 
    • 逻辑运算少加了括号。
    //注意下面的括号,丢了很严重,不要问我怎么知道的 
           for(int i=2;i<=N;i++) Rank[sa[i]]=Rank[sa[i-1]]+(A[sa[i]]==A[sa[i-1]]&&B[sa[i]]==B[sa[i-1]]?0:1);
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<string>
    using namespace std;
    const int maxn=2000010;
    char ch[maxn];
    int min(int a,int b)  { if(a<b) return a;return b;}
    struct SA
    {
        int Rank[maxn],sa[maxn],tsa[maxn],A[maxn],B[maxn],cntA[maxn],cntB[maxn],N;
        int ht[maxn],Min[maxn][30];
        int sort()
        {
            N=strlen(ch+1);
            for(int i=0;i<=256;i++) cntA[i]=0;
            for(int i=1;i<=N;i++) cntA[ch[i]-'a'+1]++;
            for(int i=1;i<=256;i++) cntA[i]+=cntA[i-1];
            for(int i=N;i>=1;i--) sa[cntA[ch[i]-'a'+1]--]=i;
            Rank[sa[1]]=1;
            for(int i=2;i<=N;i++)  Rank[sa[i]]=Rank[sa[i-1]]+(ch[sa[i]]==ch[sa[i-1]]?0:1);//这个括号不要少。 
            for(int l=1;Rank[sa[N]]<N;l<<=1){
                for(int i=0;i<=N;i++) cntA[i]=cntB[i]=0;
                for(int i=1;i<=N;i++) cntA[A[i]=Rank[i]]++;
                for(int i=1;i<=N;i++) cntB[B[i]=i+l<=N?Rank[i+l]:0]++;
                for(int i=1;i<=N;i++) cntA[i]+=cntA[i-1],cntB[i]+=cntB[i-1];
                for(int i=N;i>=1;i--) tsa[cntB[B[i]]--]=i;
                for(int i=N;i>=1;i--) sa[cntA[A[tsa[i]]]--]=tsa[i];
                Rank[sa[1]]=1;//注意下面的括号,丢了很严重,不要问我怎么知道的 
                for(int i=2;i<=N;i++) Rank[sa[i]]=Rank[sa[i-1]]+(A[sa[i]]==A[sa[i-1]]&&B[sa[i]]==B[sa[i-1]]?0:1);
            }
        }
        int height(){
            for(int i=1,j=0;i<=N;i++){
                if(j) j--;
                while(ch[i+j]==ch[sa[Rank[i]-1]+j]) j++;
                ht[Rank[i]]=j;
            }
        }
        int get_rmq()
        {
            for(int i=1;i<=N;i++)  Min[i][0]=ht[i];
            for(int j=1;(1<<j)<=N;j++){
                for(int i=1;i+(1<<j)-1<=N;i++) 
                 Min[i][j]=min(Min[i][j-1],Min[i+(1<<(j-1))][j-1]);
            }
        }
        int query_rmq(int L,int R)
        {
            if(L>R) swap(L,R); L++;
            int k=log2(R-L+1);
            return min(Min[L][k],Min[R-(1<<k)+1][k]);
        }
        void solve()//solve这一段是抄的,说实话我觉得有点乱。。。 
        {
            int ans=0,al=0,ar=0;
            for(int L=1;L*2<=N;L++){        
                for(int i=0;L*(i+1)+1<=N;i++){
                    int x=L*i+1,y=L*(i+1)+1;
                    if(ch[x]!=ch[y]) continue;    
                    int z=query_rmq(Rank[x],Rank[y]);
                    int t1=y+z-1,t0=0;
                    for(int j=0;j<=L-1;j++){ 
                        if(x-j<1 || ch[x-j]!=ch[y-j]) break;
                        t0=x-j;int now=((t1-t0+1)/L);
                        if(now>ans || (now==ans && Rank[t0]<Rank[al])){
                            ans=now;al=t0;ar=t0+now*L-1;
                        }
                    }
                }
            }
            if(ans==0)  printf("%c
    ",ch[sa[1]]);
            else {
                for(int i=al;i<=ar;i++)  printf("%c",ch[i]);printf("
    ");
            }
        }
    }Sa;
    int main()
    {
        int Case=0;
        while(~scanf("%s",ch+1)){
            if(ch[1]=='#') return 0; 
            printf("Case %d: ",++Case); 
            Sa.sort();
            Sa.height();;
            Sa.get_rmq();
            Sa.solve();
        }  return 0; 
    }
  • 相关阅读:
    js Map的使用
    javascript的Map使用
    解决vue视图不渲染
    SVN提示is already locked 解决办法
    AS报:Manifest merger failed with multiple errors, see logs
    使用Hbuilder手机debug
    在Html页面中调用ajax代码
    JAVA跨域CORS
    vue2.0的初始化
    jquery的$(selector).each(function(index,element))和$.each(dataresource,function(index,element))的区别
  • 原文地址:https://www.cnblogs.com/hua-dong/p/8016916.html
Copyright © 2011-2022 走看看