题目链接:http://poj.org/problem?id=1961
题意:给定长度为n的字符串S,求其前i位重复的次数K。
思路:求出next[]数组(字符串下标从0开始)。然后从2开始枚举到len,如果X%(X-next[X])==0且X/(X-next[X])>1,则前X个满足题意,循环次数为X/(X-next[X])。
证明:有一点很明显,如果X能整除X-next[X],那么next[X]>=X/2。
加一个点E,满足AC=ED,那么由next[]数组的定义可知:0(A点)到next[X]-1(C点)这个子串和从X-next[X](E点)到X-1(D点)这个子串相等,所以ab=hi,hi=bc,bc=ij,……fg=mn,而X-next[X]就等于mn,所以X/(X-next[X])就是循环的次数。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX=1000005;
int next[MAX],n,num=0;
char s[MAX];
void getNext(char s[],int len,int next[])
{
next[0]=-1;
int i=0,j=-1;
while(i<len)
{
if(j==-1||s[i]==s[j]) next[++i]=++j;
else j=next[j];
}
}
int main()
{
while(scanf("%d",&n),n)
{
scanf("%s",s);
getNext(s,n,next);
int i,j;
printf("Test case #%d\n",++num);
for(i=2;i<=n;i++)
{
j=i-next[i];
if(i%j==0&&i/j>1) printf("%d %d\n",i,i/j);
}
puts("");
}
return 0;
}