Period
Time Limit: 3000MS Memory Limit: 30000K
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 AK ,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
Sample Output
Test case #1
2 2
3 3
Test case #2
2 2
6 2
9 3
12 4
主要是KMP求最小循环节的原理,要求对next数组有一定的理解。
如图所示,next的数值意义是其下标以前的字符串前缀和后缀的最大重合度,明显 2 - 1 ,3 - 2,4-3,5-4。是完全相等的(从2到5,1到4这一大段都是相等的,毫无疑问其对应等分的子串也相等)。but,1-1,2-2,3-3,4-4,5-5。这些子串本身与本身相等更加不用说了。那么由这些关系,不难推导出12345每个部分都是相等的。假设当前字符串长度为len,则子串1等于len-next(len)。当满足len%(len-next(len)) == 0时(子串1可以被整个串等分),上诉情况才成立。
针对这题的话就是把整个串的长度枚举一遍然后处理输出就好了。而len/(len-next(len)) 就是循环节出现次数
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int _next[1000010];
char ch[1000010];
void getnext(char *ch)
{
memset(_next,0,sizeof _next);
long len = strlen(ch),i = 0,j = -1;
_next[0] = -1;
while (i < len){
if (j == -1 || ch[i] == ch[j]){
i++;
j++;
_next[i] = j;
}
else{
j = _next[j];
}
}
}
int main ()
{
long k,cut = 0;
while (~scanf ("%ld",&k) && k){
scanf ("%s",ch);
cout << "Test case #" << ++cut <<endl;
long len = strlen(ch);
getnext(ch);
for (long i = 2;i <= len; i++){
if (_next[i] && i % (i-_next[i]) == 0){
cout << i << ' ' << i / (i-_next[i]) << endl;
}
}
cout << '\n';
}
return 0;
}