传送门:点击打开链接
KMP算法是一种字符串匹配算法,我理解为对字符串暴搜的优化,难点在next函数的求值,看了两天还是没有完全弄懂next数组的意思
可以写出函数但是对其中的递归实现只是在看明白了的状态。
但是对next数组也有一点优化。
next数组中值:对应字符前的字符串的最大相同前后缀长度
这是在网上看其他dalao的文章的算法总结写的代码,侵删致歉。
AC代码
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAX = 1e6 + 5;
int Next[MAX];
char S[MAX], P[MAX];
int KMP(char *s1, char *s2){
int m1 = strlen(s1), m2 = strlen(s2);
Next[0] = 0;
int ans, j;
ans = 0;
j = 1;
while(j < m2){
int k = Next[j - 1];
while(s2[j] != s2[k] && k){ //两字符不等,函数值与上一字符函数值相同
k = Next[k - 1];
}
if(s2[j] == s2[k]) //新比较的字符相等,函数值加一
Next[j] = k + 1;
else
Next[j] = 0; //新比较字符不等,跳回首字符
j++;
}
j = 0;
for(int i = 0; i < m1; i++){
while(s1[i] != s2[j] && j){ //出现不匹配的情况,根据next函数值右移指定大小
j = Next[j - 1];
}
if(s1[i] == s2[j]) //相匹配后,右移继续判断
j++;
if(j == m2){ //出现成功匹配的情况,答案加一
ans++;
}
}
return ans;
}
int main(){
int N;
cin>>N;
while(N--){
cin>>P;
cin>>S;
cout<<KMP(S, P)<<endl;
}
return 0;
}
这里有一个大坑需要注意,因为其他大佬博客上的讲解都是next值,所以我直接把数组命名为next,写完之后再Dev-C++里跑起来运行结果也是正确的,然后自信满满的提交,于是,我就CE了,下图从下数第三个AC是我直接换了大佬的代码提交来实验的,发现可以过,然后一直改一直改,直到把next全部改为Next才AC,但是因为当时改了不止这一项,就一个个还原看究竟是哪里出了问题,最终发现罪魁祸首是next,之后也在网上查了这个问题,next并不是C++关键字,但是在C++里开next[] 必须初始化,但是其他数组名不受此限制。