题目:KMP字符串匹配
思路:加注释重写~
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000000
char a[maxn+5],b[maxn+5]; //a为文本串,b为模式串
int n,m; //a、b的长度
int nxt[maxn+5]={0}; //0~i的公共前后缀长
void readin() { //读入
scanf("%s%s",a,b);
n=strlen(a),m=strlen(b);
}
void make_nxt() { //初始化nxt数组
nxt[0]=-1; //为了回避数组超下界,这里的nxt[i+1]表示nxt[i]
for(int i=0;i<m;i++) {
int j=nxt[i]; //[0,j]始终等于[i-j,i]
while(b[i]!=b[j]&&j>=0) { //通过[1,i]的公共前后缀长来推导[1,i+1]的公共前后缀长
j=nxt[j]; //[1,nxt[j]]的最长公共前后缀,一定也同时是[1,j]的公共前后缀,同时是[1,i]的公共前后缀
}
nxt[i+1]=j+1;
}
//此时的nxt需整体前移
for(int i=0;i<m;i++) nxt[i]=nxt[i+1];
}
void mtch(){ //匹配
int j=0;
for(int i=0;i<n;i++) {
while(j&&a[i]!=b[j]) { //找到第一个b[0,j]可以匹配上a[0,i]的位置
j=nxt[j-1];
}
if(a[i]==b[j]) j++; //为了防止j==0要加一步判断
if(j==m){
printf("%d\n",i-m+2); //输出
j=nxt[j-1];
}
}
for(int i=0;i<m;i++) printf("%d ",nxt[i]);
}
int main(){
readin();
make_nxt();
mtch();
return 0;
}