参考:http://www.cnblogs.com/yefeng1627/archive/2013/04/28/3050027.html
KMP用的是白书的模板
(1)关于KMP的理解,和拓展KMP的理解
KMP是和串的前缀的后缀的最大匹配长度,拓展KMP是和串的后缀的前缀的最大匹配长度
(2)next的几个性质:
1)next的代表含义
a.next[i]表示比配到i失配是,应匹配的位置
b.next[i]表示长度为i的前缀串的最大prefix-suffix值
2)判断前缀串是否为循环串
a.i % (i - next[i]) == 0则为循环串
b.i % (i - next[i]) == 0则不为循环串
3)最小循环节,循环次数(通常要求循环节不等于n,循环次数>1.即f[i]>0)
前提是循环串,即i % (i - next[i]) == 0,则最小循环节 = i - next[i]; 循环次数 = i / (i - next[i])
4)最小覆盖子串
可以是循环串也可以不是循环串,n-next[n]
5)求所有的前后缀值
利用f[]数组,迭代计算
!!next的理解,i%(i - next[i])的理解
。。。
POJ 2752 Seek the Name, Seek the Fame
题目5)的情况,求所有的前后缀值
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <cmath> #include <stack> using namespace std; const int maxn = 500010; char p[maxn]; int f[maxn]; int n; void getFail(char p[], int f[]) { int l = strlen(p); f[0] = f[1] = 0; for (int i = 1; i < l; i++) { int j = f[i]; while (j && p[i] != p[j]) j = f[j]; f[i + 1] = p[i] == p[j] ? j + 1 : 0; } } stack<int>st; int main() { int step = 1; while (~scanf("%s", p)) { while (!st.empty()) st.pop(); getFail(p, f); n = strlen(p); int i = n; while (i) { st.push(i); i = f[i]; } while (!st.empty()) { int x = st.top(); printf("%d", x); if (x == n) puts(""); else printf(" "); st.pop(); } } }
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <cmath> using namespace std; const int maxn = 1000010; char p[maxn]; int f[maxn]; int n; void getFail(char p[], int f[]) { int l = strlen(p); f[0] = f[1] = 0; for (int i = 1; i < l; i++) { int j = f[i]; while (j && p[i] != p[j]) j = f[j]; f[i + 1] = p[i] == p[j] ? j + 1 : 0; } } int main() { int step = 1; while (cin >> n && n) { scanf("%s", p); printf("Test case #%d\n", step++); getFail(p, f); int l = strlen(p); for (int i = 2; i <=l; i++ ) { if (i - f[i] != i && i % (i - f[i]) == 0) cout << i << ‘ ‘ << i / (i - f[i]) << endl; } cout << endl; } }
二维的情况+最小覆盖长度
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <cmath> using namespace std; const int maxn = 10010; char p[maxn][100]; int fr[maxn], fc[100]; int nr, nc; int check_r(int x, int y) { int c = strcmp(p[x], p[y]); if (c == 0) return 1; else return 0; } int check_c(int x, int y) { for (int i = 0; i < nr; i++) if (p[i][x] != p[i][y]) return 0; return 1; } int getFail_r(int f[]) { f[0] = f[1] = 0; for (int i = 1; i < nr; i++) { int j = f[i]; while (j && !check_r(i, j)) j = f[j]; f[i + 1] = check_r(i, j) ? j + 1 : 0; } return nr - f[nr]; } int getFail_c(int f[]) { f[0] = f[1] = 0; for (int i = 1; i < nc; i++) { int j = f[i]; while (j && !check_c(i, j)) j = f[j]; f[i + 1] = check_c(i, j) ? j + 1 : 0; } return nc - f[nc]; } int main() { while (cin >> nr >> nc) { for (int i = 0; i < nr; i++) scanf("%s", p[i]); int rr = getFail_r(fr); int cc = getFail_c(fc); cout << 1LL * cc * rr << endl; } } /* ABCDEFAB BCDEFABC CDEFABCD DEFABCED ABCDEFAB BCDEFABC */
原文:http://blog.csdn.net/guognib/article/details/20776125