ZOJ1905Power Strings (KMP||后缀数组+RMQ求循环节)

Posted ---学习ing---

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ZOJ1905Power Strings (KMP||后缀数组+RMQ求循环节)相关的知识,希望对你有一定的参考价值。

Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of concatenation as multiplication, exponentiation by a non-negative integer is defined in the normal way: a^0 = "" (the empty string) and a^(n+1) = a*(a^n).

 

Input

 

Each test case is a line of input representing s, a string of printable characters.


<b< dd="">

Output

 

For each s you should print the largest n such that s = a^n for some string a. The length of s will be at least 1 and will not exceed 1 million characters. A line containing a period follows the last test case.

 

Sample Input

abcd
aaaa
ababab
.

 

Sample Output

1
4
3

 

求最大循环长度。

KMP可以求,之前做过,见。

http://www.cnblogs.com/hua-dong/p/8016873.html

http://www.cnblogs.com/hua-dong/p/8016916.html

这里实现了后缀数组(不过好像被卡了,只能同KMP实现)。

#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
int min(int x,int y) { if(x<y) return x;return y;}
using namespace std;
const int maxn=1000010;
char ch[maxn];
struct SA
{ 
    int Rank[maxn],sa[maxn],tsa[maxn],A[maxn],cntA[maxn],B[maxn],cntB[maxn];
    int ht[maxn],Min[maxn][30],N;
    void get_SA()
    {
        N=strlen(ch+1);
        for(int i=0;i<=300;i++) cntA[i]=0;
        for(int i=1;i<=N;i++)  cntA[ch[i]]++;
        for(int i=1;i<=300;i++) cntA[i]+=cntA[i-1];
        for(int i=N;i>=1;i--)  sa[cntA[ch[i]]--]=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=1;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);
        }
    }
    void get_hgt()
    {
        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;
        }
    }
    void get_rmq()
    {
        for(int i=1;i<=N;i++) Min[i][0]=ht[i];
        for(int i=1;(1<<i)<=N;i++)
         for(int j=1;j+(1<<i)-1<=N;j++){
              Min[j][i]=min(Min[j][i-1],Min[j+(1<<(i-1))][i-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()
    {
        int ans=1;
        for(int i=1;i<=N;i++){
            if(N%i!=0) continue;
            if(i+query_rmq(Rank[1],Rank[1+i])==N) {
                ans=N/i; break;
            }
        }   printf("%d\\n",ans);
    }
}Sa;
int main()
{
    while(~scanf("%s",ch+1)){
        if(ch[1]==\'.\') return 0;
        Sa.get_SA();
        Sa.get_hgt();
        Sa.get_rmq();
        Sa.solve(); 
    }  return 0;
}

 

以上是关于ZOJ1905Power Strings (KMP||后缀数组+RMQ求循环节)的主要内容,如果未能解决你的问题,请参考以下文章

POJ-2406 Power Strings(KMP)

poj 2406 Power Strings(kmp)

Power Strings--KMP

POJ2406Power Strings[KMP 失配函数]

POJ2406-Power Strings(kmp循环节)

poj 2406 Power Strings(KMP)