题目地址: http://poj.org/problem?id=2406
KMP 。
NEXT 数组的扩展运用。
求字符串的最小循环节。(反过来说,就是求最小覆盖子串:len-next[len])
我们判断 NEXT [ LEN ] 就行了,可以得到字符串是否重复出现。如果不重复出现,循环节为1。否则:
1. 如果重复出现的两部分,存在重叠,那么循环节一定是len / (len - next[len])。即 len / [非重复部分的长度]。
当然,必须能够整除,比如ababab,重复部分为ab,6%2。而不能够整除时,比如ababa则不行,重复部分为a,5%2。(具体证明自己想)
2. 如果不重叠,假如两端重复刚好各占原字符串的一半,那么也是len / (len - next[len]),比如abcabc。
3. 否则循环节为1,比如abcdabc。
#include<cstdio>
const int MAXN = 1000100;
int nxt[MAXN];
int get_next(char *ptr){
int i,j;
nxt[0]=0;
for(i=1;ptr[i];i++){
j=nxt[i-1];
while(ptr[i]!=ptr[j] && j)
j=nxt[j-1];
nxt[i]=ptr[i]==ptr[j]?j+1:0;
}
return i;
}
char s[MAXN];
int main(){
int i,len;
while(gets(s)){
if(s[0]=='.' && !s[1]) break;
len=get_next(s);
if(len%(len-nxt[len-1])==0)
printf("%d\n",len/(len-nxt[len-1]));
else puts("1");
}
return 0;
}