KMP算法
理解
KMP算法的核心,是一个被称为部分匹配表(Partial Match Table)的数组。我觉得理解KMP的最大障碍就是很多人在看了很多关于KMP的文章之后,仍然搞不懂PMT中的值代表了什么意思。这里我们抛开所有的枝枝蔓蔓,先来解释一下这个数据到底是什么。
对于字符串“abababca”,它的PMT如下表所示:
PMT中的值是字符串的前缀集合与后缀集合的交集中最长元素的长度。
我们看到如果是在 j 位 失配,那么影响 j 指针回溯的位置的其实是第 j −1 位的 PMT 值,所以为了编程的方便, 我们不直接使用PMT数组,而是将PMT数组向后偏移一位。我们把新得到的这个数组称为next数组。
例题
给定两个数组,问能不能再第一个数组中匹配得到第二个数组,如果可以,那么输出最早匹配的起始位置,否则输出-1
代码:
#include<bits/stdc++.h>
using namespace std;
int s[1000005],p[10005], ne[10005];//next是关键字
int n, m;
void getNext(){
int i = 0, j = -1;
ne[0] = -1;
while(i < m){
if(j == -1 || p[i] == p[j]){
i++; j++; ne[i] = j; //attention!
}
else j = ne[j];
}
}
int KMP(){
int i = 0, j = 0;
getNext();
while(i < n &&j <m){
if(j == -1 || s[i] == p[j]){
i++; j++;
}
else j = ne[j];
}
if(j == m) return i - j + 1;
return -1;
}
int main(){
int t;
cin >> t;
while(t--){
cin >> n >> m;
for(int i = 0; i <n; i++) scanf("%d",&s[i]);
for(int i = 0; i < m ;i++) scanf("%d",&p[i]);
int t = KMP();
cout << t << endl;
}
system("pause");
}