网上好多说得不够清楚,不过真正理解了KMP的next数组的含义,一点就通了。非优化的next数组的含义是:next[i]=k表示模式串下标为i的字符的前k个字符与开头的前k个字符相等,那么从0到i-1的模式串必然是循环的,循环节为从0到next[i] - (2 * next[i] - i),其中 2 * next[i] - i表示的是从后往前的部分与从前往后的部分相交的长度。
/*
* hdu1358/linux.cpp
* Created on: 2011-8-29
* Author : ben
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define MAXN 1000005
int N;
char str[MAXN];
int nextval[MAXN];
void work();
int main() {
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
#endif
work();
return 0;
}
void get_nextval() {
int i = 0, j = -1;
int parlen = N;
char *pattern = str;
nextval[0] = -1;
while (i < parlen) {
if (j < 0 || pattern[i] == pattern[j]) {
i++;
j++;
if (pattern[i] != pattern[j]) {
nextval[i] = j;
} else {
nextval[i] = nextval[j];
}
} else {
j = nextval[j];
}
}
}
void get_next() {
int i = 0, j = -1;
int parlen = N;
char *pattern = str;
nextval[0] = -1;
while (i <= parlen) {
if (j == -1 || pattern[i] == pattern[j]) {
i++;
j++;
nextval[i] = j;
} else {
j = nextval[j];
}
}
}
void work() {
int T = 0, tmp;
while (scanf("%d", &N) == 1 && N > 0) {
scanf("%s", str);
get_next();
printf("Test case #%d\n", ++T);
for (int i = 2; i <= N; i++) {
tmp = i - nextval[i];
if (i % tmp == 0 && i / tmp > 1) {
printf("%d %d\n", i, i / tmp);
}
}
putchar('\n');
}
}