总结了下,关于BF算法,以及KMP。遇到后缀数组的时候突然发现,KMP还是有用的啊~~~后缀数组更简单,就是代码比较长~~
/*
记住一个公式:KMP算法=BF算法+next数组
->1.BF算法中,只需要将j=next[j],避免回溯就行了。所以计算 next数组
->2.计算next数组
做两个变量j,k
j=0(用于记录计算P串的位置,j=0~(n-1),最有一个不用计算)
k=-1(记录k在P串位置的前后串最长公共前后缀)
******理解下:0~k~(n-1)分k左右一个串,左右串中存在k之前的串与,
后面j(j一般在k~n之间)之前的串相等。然后看next函数里面的递推关系就比较容易理解了 ,简单吧,书上讲解的太蛋碎了~~
adsadjkhasdadabcabdabcabcaaasdasda
abcabdabcabcaa
13
*/
#include<iostream>
using namespace std;
const int MAXN=1<<7;
char T[MAXN],P[MAXN],next[MAXN];;
int N;
void input(){
scanf("%s",T);
scanf("%s",P);
}
/*
ababdabcd
abc
*/
int BF(){
int n=strlen(T),m=strlen(P);
int i=0,j=0;
while(i<n){
if(T[i]==P[j]){
i++;
j++;
}else{
i=i-j+1;
j=0;//j=next[j];就是KMP算法了。next数组避免了j=0的回溯!!!!!!!
}
if(j==m) return i-j;
}
return -1;
}
/*
由BF改进过来的KMP
*/
int KMP(){
int n=strlen(T),m=strlen(P);
int i=0,j=0;
while(i<n){
if(T[i]==P[j]){
i++;
j++;
}else{
i=i-j+1;
j=next[j];
}
if(j==m) return i-j;
}
return -1;
}
int getNext(){
int n=strlen(P);
next[0]=-1;
int j=0,k=-1;
while(j<(n-1)){
if(k==-1 || P[j]==P[k]){
j++;
k++;
next[j]=k;
/*
//将next[j]=k;替换成下面的代码,避免了next中k的回溯
if(P[j]!=P[k]){
next[j]=k;
}else
next[j]=next[k];
*/
}else{
k=next[k];
}
}
return *next; //其实可以返回void类型的,但是就是想测试下如何返回数组来着。这个多余了。
}
int main(){
input();
printf("BF:%d\n",BF());
getNext();
int i=0,n=strlen(P);
while(i<n) printf("%d ",next[i++]);
printf("\n");
printf("KMP:%d\n",KMP());
return 0;
}
KMP瞬间简单了吧~~~~看书会死人的~~