KMP算法

来源:互联网 发布:电竞椅 知乎 编辑:程序博客网 时间:2024/06/05 00:43

菜鸟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];}elsej=next[j];//先直接进入else 

然后

if(p[j]==p[i]){next[i+1]=j+1;i++;j=next[i];}//接着再进入if elsej=next[j]; 


"abaaa"  p[j]=p[1]='b'!=p[i],回去j=next[j]=next[1]=0.然而,p[j]=p[0]='a'!=p[i]='a',咋整呀,也回不去了,这时候又进入这种状况


  1.  if(j==0&&p[j]!=p[i]){  
  2.             next[i+1]=0;  
  3.             i++;  
  4.             j=next[i];    
  5.         }  

····························直接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];}elseif(p[j]==p[i]){next[i+1]=j+1;i++;j=next[i];}elsej=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++;elsej=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];}elseif(p[j]==p[i]){next[i+1]=j+1;i++;j=next[i];}elsej=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++;elsej=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); }




原创粉丝点击