字符串模式匹配(KMP)
给定一个字符串 text 和一个模式串 pattern,求 pattern 在text 中的出现次数。text 和 pattern 中的字符均为英语大写字母或小写字母。text中不同位置出现的pattern 可重叠。
输入格式:
输入共两行,分别是字符串text 和模式串pattern。
输出格式:
输出一个整数,表示 pattern 在 text 中的出现次数。
输入样例1:
zyzyzyz
zyz
输出样例1:
3
输入样例2:
AABAACAADAABAABA
AABA
输出样例2:
3
数据范围与提示:
1≤text, pattern 的长度 ≤10
6
, text、pattern 仅包含大小写字母。
本题关于KMP算法这一点,我能力有限,无法做出更加详细的解释
点击前往july博客 这道题就是在kmp的基础上,如果找到一个子串后,不要return,先让计数器++,再让i–,即返回到上一个字符,让j=next[j-1],即假设第j个字符失配,然后继续执行相关操作即可.还有一点就是,作者能力有限,不知道为什么一改成优化后的next数组就不对,不优化就对了,如果有谁知道的话,欢迎下方评论指教.
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
char s[1000005],p[1000005];
int Next[1000005];
void GetNext(int pLen){
int k=-1;
Next[0]=-1;
int j=0;
while(j<pLen){
if(k==-1||p[j]==p[k]){
j++;
k++;
Next[j]=k;
}else {
k=Next[k];
}
}
}
int KMP(int sLen,int pLen){
int i=0;
int j=0;
int cnt=0;
while(i<sLen&&j<pLen){
if(j==-1||s[i]==p[j]){
i++;
j++;
}else{
j=Next[j];
}
if(j==pLen)cnt++,j=Next[j-1],i--;
}
return cnt;
}
int main(){
int sLen,pLen;
for(sLen=0;(s[sLen]=getchar())!='\n';sLen++);
for(pLen=0;(p[pLen]=getchar())!='\n';pLen++);
GetNext(pLen);
cout<<KMP(sLen,pLen);
}