#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]的匹配