算法讲解:
kmp算法一般都是用于字符串匹配问题的,那么我们不妨先看看暴力的kmp字符串匹配是如何的吧。
这个算法不用看,其算法复杂度为O(n*m)。
KMP:
那么kmp又是如何的呢?我们要搞懂kmp算法我们要先搞懂next数组,其next[i]定义为前i个字母构成的字符串中与前缀匹配的最长的后缀长度。
看定义感觉非常晦涩难懂,其实不然很简单,我们先来搞懂后缀和前缀是干嘛的就行
前缀:包含首位字符但不包含末位字符串的子串
后缀:包含末位字符但不包含首位字符的子串
next[i]:其值:第i位字符前面i-1位字符组成的子串的前后缀重合字符数加一
对于定义举个例子:
那么我们我们拥有这个next数组之后有啥用呢?且听我慢慢道来:
题目详解
上面这张图解释了在为短串求next数组中下标j的含义
#include <iostream>
using namespace std;
const int N = 100010 , M =1000100;
char p[N],s[M];
int ne[N];
int main(){
int n;
scanf("%d%s",&n,p+1);
int m;
scanf("%d%s",&m,s+1);
//初始化next数组
for(int i=2, j=0;i<=n;i++){
//j代表前缀和后缀匹配的最大长度
while(j && p[i] != p[j+1]) j = ne[j];
if(p[i] == p[j+1]) j++;
ne[i] = j;
}
//借助next数组比较s和p两个字符串
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++;
// cout<<"i:"<<i<<" j:"<<j<<endl;
if(j == n) cout<<i - n<<" ";
}
}