KMP 算法(Knuth-Morris-Pratt 算法)是一个著名的字符串匹配算法,效率很高.
基本实现方法:
1、构建一个数组决定在pattern遇到什么字符时做什么回退操作
2、搜索
实现的效果图:
模板代码1
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1010;
string pattern;
string text;
int fail[1010];
int go(int s,char next){
if(pattern[s]==next){
return s+1;
}else if(s==0){
return 0;
}else{
return go(fail[s],next);
}
}
int main(){
cin>>pattern>>text;
//构建一个 next[]/fail[]数组,基于pattern;
fail[1]=0;
for(int i=1;i<pattern.size();i++){
fail[i+1]=go(fail[i],pattern[i]);
}
//开始寻找
int s=0;
for(int i=0;i<text.size();i++){
s=go(s,text[i]);
if(s==pattern.size()){
cout<<"Found! "<<i-pattern.size()+1<<endl;
}
}
}
代码模板2
int i,j;
scanf("%s",a+1);
scanf("%s",b+1);
la=strlen(a+1);
lb=strlen(b+1);
for(i=2,j=0;i<=lb;i++) {//自身匹配
while(j&&b[i]!=b[j+1])
j=p[j];
if(b[i]==b[j+1])
j++;
p[i]=j;
}
for(i=1,j=0;i<=la;i++) {//A与B匹配
while(j&&a[i]!=b[j+1])
j=p[j];
if(a[i]==b[j+1])
j++;
// f[i]=j;//记录结果
// St[++top]=i;//入栈
if(j==lb)//如果匹配成功,弹出,并更新j值
// top-=lb,j=f[St[top]];
}
实现这个算法分别需要解决的问题
依据txt被指向的字符和pat被指向的字符在next的决策进行状态转移
go
int go(int s,char next){
if(pattern[s]==next){
return s+1;
}else if(s==0){
return 0;
}else{
return go(fail[s],next);
}
}
cout
for(int i=0;i<text.size();i++){
s=go(s,text[i]);
if(s==pattern.size()){
cout<<"Found! "<<i-pattern.size()+1<<endl;
}
}
书写next/dp数组
利用自动机解释代码
利用字符串取模解释代码的可行性和正确性
fail数组其本质意义就是在pattern中前n个对pattern本身取模的结果
(取模本质就是对后缀进行匹配,故在取模中,首位的优先级最低,并不断删除首位并取模)
//开始寻找
int s=0;
for(int i=0;i<text.size();i++){
s=go(s,text[i]);
if(s==pattern.size()){
cout<<"Found! "<<i-pattern.size()+1<<endl;
}
}