KMP算法思想
KMP算法是D.E.Knuth,J.H.Morris和V.R.Pratt共同提出的,简称为KMP算法。
该算法较BF算法有较大的改进:每当一趟匹配过程中出现字符不相等时,主串指示器 i 不用回溯,而是利用已经得到的“部分匹配”结果,将模式串向右“滑动”尽可能远的一段距离后,与 i 对齐,继续进行比较。
KMP算法过程示例
当 i = 3,j = 3时失配。
此时按照BF算法,将子串P右移一位:
按照KMP算法,尽可能的多移几位,i 的位置不变,使得模式P中的某个位置继续与 i 进行比较:
发现当 i = 7,j = 5时失配:
模式P继续向右滑动,进行第三次匹配:
此时匹配完成。
确定next[ ] 函数
因此我们需要对模板s[ ]进行预处理:
以 i 为终点的后缀 = 从1开始的前缀,且长度最长
即next[ i ] = j :
s[ 1…j ]这一段 = s[ i-j+1 … i ] 这一段
C++代码实现
注:s[ ]下标从1开始,p[ ]下标从0开始,所以s[ i ] 对应的是p[ j+1 ]
#include<iostream>
#define N 10010
#define M 100010
using namespace std;
int main()
{
int n, m;
char s[M], p[N];
int ne[N];
cin >> n >> p+1 >> m >> s+1;
for(int i = 2, j = 0; i <= n; i++) //求出 next[]
{
while(j && p[i] != p[j+1])
j = ne[j];
if(p[i] == p[j+1])
j++;
ne[i] = j;
}
for(int i = 1, j = 0; i <= m; i++) //KMP算法
{
while(j && s[i] != p[j+1])
j = ne[j];
if(s[i] == p[j+1])
j++;
if(j == n)
{
printf("%d ", i-n);
j = ne[j];
}
}
return 0;
}