菜鸟KMP算法钻研之路,花了一下午,QAQ,自己理解写下的。
KMP算法 主要被分解为以下两个函数:
1,GetNext(string p,int next[]),通过这个函数获得关于p的next数组。
关于next数组:1,大小为p.getlength()+1,因为下标从1到p.getlength(),next[0]没用到,就赋值其为next[0]=-1;
2,next[i]的值:返回p[0]到p[i-1]子串中最大公共串的大小。(公共串:emmmQAQ不会定义,举个例子,假设子串为ABABA,那最大的公共串为ABA(因为前三 ABA后三ABA),此时next[i]=3).
3,如何求next[i+1],利用next[i]求next[i+1],初始的next[1]=0.下面举个例子:
比如有一串为"abaaabba"
子串分解 "a" ,此时i=1,next[i]=0,j=next[i]=0;
"ab",p[j]='a',因为p[j]!=p[i],那么此时next[i+1]=0(next[2]求得),i++,j=next[i]=0,此情况的代码如图
if(j==0&&p[j]!=p[i]){
next[i+1]=0;
i++;
j=next[i];
}
"aba",因为p[j]=‘a’,p[i]='a'=p[j],那么此时next[i+1]为next[i]+1(next[3]求得)即j+1=1;公共串为'a',i++,j=next[i] 此情况的代码如图
if(p[j]==p[i]){
next[i+1]=j+1;
i++;
j=next[i];
//状况一
}
"abaa":因为p[j]='b'!=p[i]='a',不行要退一步,j=next[j],得到p[j]=p[0]='a',p[j]=p[i]可以了,那么next[i+1]=j+1(next[4]求得),然后i++,j回来j=next[i]此情 况的到代码如图
if(p[j]==p[i]){
next[i+1]=j+1;
i++;
j=next[i];
}
else
j=next[j];//先直接进入else
然后
if(p[j]==p[i]){
next[i+1]=j+1;
i++;
j=next[i];
}//接着再进入if
else
j=next[j];
"abaaa" p[j]=p[1]='b'!=p[i],回去j=next[j]=next[1]=0.然而,p[j]=p[0]='a'!=p[i]='a',咋整呀,也回不去了,这时候又进入这种状况
- if(j==0&&p[j]!=p[i]){
- next[i+1]=0;
- i++;
- j=next[i];
- }
····························直接next[i+1]=0,继续i++,j回来j=next[i]。
"abaaab"
"abaaabb"
"abaaabba".........以此类推
完整代码如下
void Getnext(string p,int next[]){
int i=1;
next[0]=-1;//下标从1开始,所以next[0]=-1;
next[1]=0;//固定的
int j=next[i];
while(i<p.length()){
if(j==0&&p[j]!=p[i]){
next[i+1]=0;
i++;
j=next[i];
}
else
if(p[j]==p[i]){
next[i+1]=j+1;
i++;
j=next[i];
}
else
j=next[j];
}
}
2,GetIndex(string mainstr,string p,int index,int next[])
本菜鸟当初卡这卡了好久啊QAQ 最后辛苦改bug才知道自己之前没有认真把握好i指针的移动。
要移动处之一,两串串单个字符匹配成功i++啦;
要移动处之二,两串串单个字符匹配不成功,这时候i不要先移动,让模式串的指针j移动,j=next[j]。
移动呀 匹配不成功 那就继续移动呀 哎呀卧槽j=0移动不了了咋整,还是匹配不成功啊QAQ,这时候就要开始移动i了没错开始移动i了
然后 循环跳出的条件当然是 要么主串遍历完了,或者模式串遍历完了
当模式串遍历完了 跳出循环 返回INDEX的值
否则 返回-1表示模式串在主串不存在!
int Getindex(string mainstr,string p,int next[],int pos){
int i=pos,j=0;
while(i<mainstr.length()&&j<p.length()){
if(mainstr[i]==p[j]){
++i;++j;
}
else{
if(j==0)
i++;
else
j=next[j];
}
}
if(j==p.length()) return i-j+1;
else return -1;
}
好了 完整代码加上测试main函数
#include<iostream>
#include<string>
using namespace std;
void Getnext(string p,int next[]){
int i=1;
next[0]=-1;//下标从1开始,所以next[0]=-1;
next[1]=0;//固定的
int j=next[i];
while(i<p.length()){
if(j==0&&p[j]!=p[i]){
next[i+1]=0;
i++;
j=next[i];
}
else
if(p[j]==p[i]){
next[i+1]=j+1;
i++;
j=next[i];
}
else
j=next[j];
}
}
int Getindex(string mainstr,string p,int next[],int pos){
int i=pos,j=0;
while(i<mainstr.length()&&j<p.length()){
if(mainstr[i]==p[j]){
++i;++j;
}
else{
if(j==0)
i++;
else
j=next[j];
}
}
if(j==p.length()) return i-j+1;
else return -1;
}
int main(){
string str;
string mainstr;
cin>>mainstr;
cin>>str;
//测试
int *next=new int[str.length()+1];
Getnext(str,next);
for(int i=1;i<str.length()+1;i++)
cout<<next[i]<<" ";
cout<<endl<<Getindex(mainstr,str,next,0);
}