#include<iostream> using namespace std; #pragma warning(disable : 4996) const int MAXN = 1000; int Next[MAXN]; void get_next(char *pat, int length) { int i = 0, j = -1; Next[0] = -1; while(i < length) { if(j == -1 || pat[i] == pat[j]) { i++; j++; Next[i] = j; } else { j = Next[j]; } } } int kmp(char *text, char *pat) { int lent = strlen(text); int lenp = strlen(pat); get_next(pat, lenp); int i = 0, j = 0; while(i < lent && j < lenp) { if(j == -1 || text[i] == pat[j]) { i++; j++; } else { j = Next[j]; } } if(j >= lenp) { return i - lenp; } else { return -1; } } int main() { char text[MAXN] = {0}; char pat[MAXN] = {0}; scanf("%s%s", text, pat); printf("%d\n", kmp(text, pat)); /*for(int i = 0; i <= strlen(pat); i++) { cout << Next[i] << endl; }*/ return 0; }
next数组的理解:
不为自身的最长首尾重复子串的长度。
必须满足不以text[i]结尾的j个字符与pat串的前j个字符匹配
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #pragma warning(disable : 4996) int n, m; char text[1000], pat[1000]; int Next[1000]; void get_next() { Next[1] = 0; int i, j = 0; for(i = 2; i <= m; i++) { while(j > 0 && pat[j+1] != pat[i]) { j = Next[j]; } if(pat[j+1] == pat[i]) { j += 1; } Next[i] = j; } } int kmp() { get_next(); int i, j = 0, cnt = 0; for(i = 1; i <= n; i++) { while(j > 0 && pat[j+1] != text[i]) { j = Next[j]; } if(pat[j+1] == text[i]) { j += 1; } if(j == m) { cnt++; j = Next[j]; } } return cnt; } int main() { while(scanf("%s%s", text+1,pat+1) != EOF) { m = strlen(pat+1); n = strlen(text+1); kmp(); printf("%d\n", kmp()); } }
//cnt输出text串中含有多少pat子串
next数组的理解:
以自身结束的最长首尾重复子串的长度。
必须满足以text[i]结尾的j个字符与pat串的前j个字符匹配
-----------------------
KMP匹配的实质:
A[i-j+1..i]与B[1..j]的匹配
B[1..P[j]]与B[j-P[j]+1..j]的匹配