KMP算法(next回退分析)

来源:互联网 发布:s60v2软件 编辑:程序博客网 时间:2024/06/16 12:47

先放上代码代码如下:
类的声明(私有成员有:s1 主串 s2子串 指针p指向next数组)

#ifndef KMP_H#define KMP_H#include<iostream>#include<string>using namespace std;class KMP{private:    string s1;    string s2;    int*p;public:    KMP();    void Next();    void kmp();    ~KMP();};#endif;

类的定义

#include<iostream>#include<string>#include"KMP.h"using namespace std;KMP::KMP(){    cout<<"请输入主串:"<<endl;    cin>>s1;    cout<<"请输入子串:"<<endl;    cin>>s2;    p=new int[s2.length()];}void KMP::Next(){   int k=0;   p[0]=0;   for(int i=1; i<s2.length();i++)   {       while(k!=0 && s2[k]!=s2[i])           k=p[k-1];       if(s2[k]==s2[i])           k++;        p[i]=k;   }}void KMP::kmp(){    int move,current,count;    for(int i=0;i<s1.length();i++)    {        current=count=i;      for(int j=0;j<s2.length();j++)      {          if(s1[current++]==s2[j])              continue;          else{                        if(move=current-1-p[current]>0)              i+=move-1;              break;          }      }        if(j==s2.length())        {            if(s1.length()-current<s2.length()) {                cout<<count<<endl;                return;            }            cout<<count<<endl;        }        if(s1.length()-i<s2.length())        {            cout<<"匹配失败"<<endl;            return;        }    }}KMP::~KMP(){    delete []p;}

主函数

#include<iostream>#include"KMP.h"using namespace std;int main(){    KMP A;    A.Next();    A.kmp();    return 0;}

在这里我只分析关于next数组中核心的一部分,就是当字符串当前失配时,next数组值怎么变化。
比如aabaacaabaaX(!=c)
next数组为 0 1 0 1 2 0 1 2 3 4 5 ?
如果确定此时X是不等于c的,就为next失配。
while(k!=0 && s2[k]!=s2[i])
k=p[k-1];
此为解决方案。
但怎么理解呢?
事实上当X!=c的时候我们就意识到前后缀最大公共长度增加是没戏的了。所以要看有没有前面有没有类似..aaX
可以和后面的..aaX匹配,那就看c前面的一个字符的a的next数组K值,在这里K的值为2,说明最前面有两个值可以与最后的aaX匹配,但是不知道与X匹配。所以有s2[k]与s2[i]比较。

关于KMP算法一部分可以参考我上一篇朴素算法。有利于理解。

原创粉丝点击