之前看KMP算法觉得这个算法好难理解啊 ,现在又看了看也就那么回事。
第一部分是求kmp数组,kmp数组是什么意思呢?kmp[i] 用于记录当匹配到模式串的第 i 位之后失配,该跳转到模式串的哪个位置。或者表示s[0…i]的最长的前缀也是后缀的长度。
代码如下:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include <iostream>
#include <queue>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
int read(){
int x=0,f=1;char ch=getchar();
while (ch<'0' || ch>'9'){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*f;
}
int kmp[maxn];
int la,lb,j;
char a[maxn],b[maxn];
int main(){
scanf("%s%s",a+1,b+1);
j=0;
la=strlen(a+1);
lb=strlen(b+1);
for(int i=2;i<=lb;i++){
while(j&&b[j+1]!=b[i]) j=kmp[j];//判断j=0的意思是,如果调到第一个字符就不用跳了。
if(b[j+1]==b[i]) j++;
kmp[i]=j;
//当第i+1失配时,向前跳的位置。
}
j=0;
for(int i=1;i<=la;i++){
while(j&&b[j+1]!=a[i]) j=kmp[j];
if(b[j+1]==a[i]) j++;
if(j==lb){
printf("%d\n",i-lb+1);
j=kmp[j];
}
}
for(int i=1;i<=lb;i++){
printf("%d ",kmp[i]);
}
return 0;
}
求kmp数组时,还可以将kmp[0]=-1;则
#include<cstdio>
#include<algorithm>
#include<cstring>
#include <iostream>
#include <queue>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
int read(){
int x=0,f=1;char ch=getchar();
while (ch<'0' || ch>'9'){if (ch=='-')f=-1;ch=getchar();}
while ('0'<=ch && ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*f;
}
int kmp[maxn];
int la,lb,j;
char a[maxn],b[maxn];
int main(){
scanf("%s",a);
j=-1;
la=strlen(a);
kmp[0]=-1;
for(int i=1;i<la;i++){
while(j>-1&&a[j+1]!=a[i]) j=kmp[j];
if(a[j+1]==a[i]) j++;
kmp[i]=j;
}
for(int i=0;i<la;i++){
cout << kmp[i]+1 << " ";
}
return 0;
}