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; 
    }
  • 相关阅读:
    Python3之json模块
    How To Enable EPEL Repository in RHEL/CentOS 7/6/5?
    安装CentOS 6.x出现Disk sda contains BIOS RAID metadata
    详解hdparm: linux下的硬盘测速工具
    {转载}需要同时设置 noatime 和 nodiratime 吗?
    ubuntu17.10安装LAMP并测试部署php探针系统
    shell监控网卡状态,故障时自动重启网卡
    L2TP/IPSec一键安装脚本
    Linux系统下用find命令查找最近修改过的文件
    Hyper-V 手动导入虚机配置实例(转载)
  • 原文地址:https://www.cnblogs.com/hua-dong/p/8016916.html
Copyright © 2011-2022 走看看