难的部分是怎么弄next数组 都是从小往大推 kmp的精髓就在next数组 一旦不匹配 通过next数组找到最大匹配长度
相信我 认真看我的代码(复制到你们的编辑器中) 和我的注释 再手动模拟一下 肯定能明白 ,不明白私聊我 ~~
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
const int maxn = 10005;
string s, p;
int Next[maxn];
int cnt;
int slen, plen;
void getfail() {
memset(Next, 0, sizeof(Next));
Next[0] = 0; Next[1] = 0;
for (int i = 1; i < plen; i++) {
int j = Next[i]; //j:代表能够匹配的下标
while (j && p[i] != p[j]) {//弹出来的j 不是0 就是两个串相同的 最大下标 也就是公共长度
j = Next[j];
}
Next[i + 1] = (p[i] == p[j]) ? j + 1 : 0;
}
}
void kmp() {
int last = 0;
slen = s.size();
plen = p.size();
getfail();//求next 最大前缀
int j = 0;
for (int i = 0; i < slen; i++) {
/*假如说 在下标 == 4的时候 与主串不匹配 它就会从进入while语句 找到s[i] == p[j]
返回next【j】 然后从next【j】继续匹配
举个例子:
i下标 0 1 2 3 4 5 6 7 8 9
主串 A B C A B C D H I J
j子串 A B C A B B _
nex的 0 0 0 0 1 2 0
当i = 5时 此时j = 5 显然不匹配 进入while-- > 更新:j = 2 -- > s[i] = p[j] -- > 退出
以此类推 一直寻找......
*/
while (j && s[i] != p[j]) {//不同就往前 0 就重新找
j = Next[j]; //不然 找到当前不符合的位置 前缀又相等的情况
}
if (s[i] == p[j]) { //紧随其后 如果找到同的 继续移动 j 判断下一个
j++;
}
if (j == plen) {//计数 根据自己的需要 自己改
cnt++; //给两道题你们就知道怎么改了HDU 2087,1686
}
}
}
int main() {
//freopen("888.txt", "r", stdin);
cin >> s >> p;
kmp();
printf("%d\n", cnt);
return 0;
}