-
总Time Limit:
- 3000ms Memory Limit:
- 65536kB
-
Description
- For each prefix of a given string S with N characters (each character has an ASCII code between 97 and 126, inclusive), we want to know whether the prefix is a periodic string. That is, for each i (2 <= i <= N) we want to know the largest K > 1 (if there is one) such that the prefix of S with length i can be written as A K,that is A concatenated K times, for some string A. Of course, we also want to know the period K. Input
-
The input consists of several test cases. Each test case consists of two lines. The first one contains N (2 <= N <= 1 000 000) – the size of the string S.The second line contains the string S. The input file ends with a line, having the
number zero on it.
Output
- For each test case, output "Test case #" and the consecutive test case number on a single line; then, for each prefix with length i that has a period K > 1, output the prefix size i and the period K separated by a single space; the prefix sizes must be in increasing order. Print a blank line after each test case. Sample Input
-
3 aaa 12 aabaabaabaab 0
#include<stdio.h>
char th[1000002];int next[1000001];
void makenext(char th[], int n)
{
int i,j;
next[1]=0;
for(i=2;i<=n+1;i++)
{
int j=i-1;
while(next[j]!=0&&th[next[j]-1]!=th[i-2]){
j=next[j];
}
if(next[j]==0)
next[i]=1;
else next[i]=next[j]+1;
}
}
int main()
{
int n,i,j,N=1;
while(scanf("%d",&n)!=EOF&&n){
if(N!=1)
printf("\n");
getchar();
gets(th);
makenext(th,n);
printf("Test case #%d\n",N);
N++;
for(i=2;i<=n;i++){
if(i%(i-next[i+1]+1)==0&&i/(i-next[i+1]+1)>1){
printf("%d %d\n",i,i/(i-next[i+1]+1));
}
}
}
return 0;
}
next数组有两种,一种是以-1开头,另一种是以0开头,以0开头的和-1的写法有点不一样,但理解了意思就不难写出来,以-1开头的next数组中存的是字符串的下标,但以0开头的next数组存的是字符串的位数,求到第i位字符的最小循环节,有公式:i-next[i]+1(next数组以0开头),以-1开头的是i-next[i],注意这个循环节不一定是严格意义上的循环节,如果i%(i-next[i]+1)==0,表明到第i个字符为止,可以有循环节整数倍重复的到,重复次数为i/(i-next[i]+1)