【kmp】【后缀数组】【连续重复子串】Power Strings POJ2406

来源:互联网 发布:Windows网络适配器命令 编辑:程序博客网 时间:2024/05/15 06:36

Power Strings

Time Limit: 3000MS Memory Limit: 65536KTotal Submissions: 25921 Accepted: 10857

Description

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. 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.

Output

For each s you should print the largest n such that s = a^n for some string a.

Sample Input

abcdaaaaababab.

Sample Output

143

Hint

This problem has huge input, use scanf instead of cin to avoid time limit exceed.

Source

Waterloo local 2002.07.01




先说说后缀数组,比如ababab

我们枚举重复串的长度len

比如len=2

如果说此时满足要求,那么后缀 0 和 后缀 2 的公共部分必定有 n - len 的长度

后缀 0 :ababab
后缀 2 :abab

所以穷举 len 即可


复杂度O(N),然后后缀数组O(NlogN) + O(N)

一交poj,超时了。。。。。


后来看了网上题解才发现后缀数组确实要超时。。。都是用kmp写的


(以下转自别人博客)

对于数组s[0~n-1],计算next[0~n](多计算一位)。

考虑next[n],假设t=n-next[n],如果n%t==0,则t就是问题的解,否则解为1。

这样考虑:

比如字符串"abababab",

            a  b a b a b a b *

next     -1 0 1 2 3 4 5 6  7

考虑这样的模式匹配,将"abababab#"当做主串,"abababab*"当做模式串,于是进行匹配到n(n=8)时,出现了不匹配:

 主串      abababab#

 模式串   abababab*

于是模式串需要回溯到next[*]=7,这之前的主串和模式串对应相等,于是需要模式串向右滚动的位移是d=n-next[n]=2,即:

            123456789 

主串      abababab#

模式串       abababab*

于是可以看出,s[0~1]=s[3~4]=s[5~6]=s[7~8]。

所以位移d=n-next[n]可以看作是构成字符串s的字串(如果n%d==0,存在这样的构成),相应的重复次数也就是n/d。



这样O(N)就可以了


测评情况(POJ)(超时的是后缀数组)



C++ AC Code(kmp)

/*http://blog.csdn.net/jiangzh7By Jiangzh*/#include<cstdio>#include<cstring>char s[1000000+10];int len;int next[1000000+10];void getnext(){memset(next,0,sizeof(next));next[0]=-1;int j=0,k=-1;while(j<len){if(k==-1||s[j]==s[k]) next[++j]=++k;else k=next[k];}}int main(){freopen("poj2406.in","r",stdin);freopen("2406kmp.out","w",stdout);while(1){memset(s,0,sizeof(s));scanf("%s",s);len=strlen(s);if(!strcmp(s,".")) break;getnext();//for(int i=0;i<=len;i++) printf("%d ",next[i]);puts("");if(len!=next[len] && len%(len-next[len])==0) printf("%d\n",len/(len-next[len]));else printf("1\n");}return 0;}



C++ TLE Code(Suffix Array)

/*http://blog.csdn.net/jiangzh7By Jiangzh*/#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=1000000+10;char s[N];int rank[N],sa[N];int c[N],tmp[N];int height[N];int lcp[N];bool cmp(int *r,int a,int b,int l){ return r[a]==r[b] && r[a+l]==r[b+l]; }void DA(int n,int m){int i,j,p,*x=rank,*y=tmp;memset(c,0,sizeof(c));for(i=0;i<n;i++) c[ x[i]=s[i] ]++;for(i=1;i<m;i++) c[i]+=c[i-1];for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;for(j=1,p=1;p<n;j*=2,m=p){for(p=0,i=n-j;i<n;i++) y[p++]=i;for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;memset(c,0,sizeof(c));for(i=0;i<n;i++) c[x[y[i]]]++;for(i=1;i<m;i++) c[i]+=c[i-1];for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];swap(x,y); x[sa[0]]=0;for(p=1,i=1;i<n;i++)x[sa[i]]=cmp(y,sa[i],sa[i-1],j)?p-1:p++;}for(i=0;i<n;i++) rank[sa[i]]=i;int k=0;for(i=0;i<n;height[x[i++]]=k)for(k?k--:0,j=sa[x[i]-1];s[i+k]==s[j+k];k++);}void work(){int n=strlen(s);s[n++]='$';DA(n,'z'+1);/*for(int i=0;i<n;i++){printf("%d %d ",sa[i],height[i]);puts(s+sa[i]);}*/lcp[rank[0]]=0x3f3f3f3f;for(int i=rank[0]-1;i>0;i--) lcp[i]=min(lcp[i+1],height[i+1]);for(int i=rank[0]+1;i<n;i++) lcp[i]=min(lcp[i-1],height[i]);//for(int i=0;i<n;i++) printf("%d ",lcp[i]);puts("");for(int len=1;len<n;len++)if((n-1)%len==0){if(lcp[rank[len]]==(n-1)-len){printf("%d\n",(n-1)/len);break;}}}int main(){freopen("poj2406.in","r",stdin);freopen("poj2406.out","w",stdout);while(1){memset(sa,0,sizeof(sa));memset(rank,0,sizeof(rank));memset(c,0,sizeof(c));memset(tmp,0,sizeof(tmp));memset(s,0,sizeof(s));scanf("%s",s);if(!strcmp(s,".")) break;work();}return 0;}










原创粉丝点击