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; 
    }
  • 相关阅读:
    Unity3D游戏-愤怒的小鸟游戏源码和教程(一)
    Unity插件-ShareSDK使用指南
    Unity 3D开发-C#脚本语言的一些基础用法
    Shader的函数公式以及使用的场景
    Shader的基本用法和语法结构
    iTween的用法总结
    Unity 3D游戏-消消乐(三消类)教程和源码
    Unity 3D游戏-NPC对话系统With XML
    XML教程、语法手册、数据读取方式大全
    ReSharper2017.3的列对齐、排版格式、列对齐错误的修复
  • 原文地址:https://www.cnblogs.com/hua-dong/p/8016916.html
Copyright © 2011-2022 走看看