hdu 1358 KMP的应用

网上好多说得不够清楚,不过真正理解了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');
}
}
posted @ 2011-08-29 18:27  moonbay  阅读(162)  评论(0编辑  收藏  举报