kmp算法简介
KMP算法一种改进的模式匹配算法,是D.E.Knuth、V.R.Pratt、J.H.Morris于1977年联合发表,KMP算法又称克努特-莫里斯-普拉特操作。它的改进在于:每当从某个起始位置开始一趟比较后,在匹配过程中出现失配,不回溯i,而是利用已经得到的部分匹配结果,将一种假想的位置定位“指针”在模式上向右滑动尽可能远的一段距离到某个位置后,继续按规则进行下一次的比较。
next数组的含义
KMP的关键在于next数组。
next数组的含义为以i为终点的最长的相同前后缀。
举个例子:
ababa
i=1时,字符串为a,next[1] = 0;
i=2时,字符串为ab,next[2] = 0;
i=3时,字符串为aba
前缀为a、ab
后缀为a、ba
最长相同为a,长度为1
故next[3] = 1;
i=4时,字符串为abab
前缀为a、ab、aba
后缀为b、ab、bab
最长相同为ab,长度为2
故next[4] = 2;
i=5时,字符串为ababa
前缀为a、ab、aba、abab
后缀为a、ba、aba、baba
最长相同为aba,长度为3 故next[5] = 3;
next数组为模式串匹配失败后,可以利用的失败信息,即向前移动多少位。
kmp模版
模版默认从1开始,这样比较简洁。
#include <iostream>
using namespace std;
const int N = 100010, M = 1000010;
int n, m;
int ne[N];
char s[M], p[N];
int main()
{
cin >> n >> p + 1 >> m >> s + 1;
for (int i=2,j=0; i<=n; i++){
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++){
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;
}