再玩KMP算法

来源:互联网 发布:exp导出数据库 full=y 编辑:程序博客网 时间:2024/06/02 05:54

  废话少说,我把代码弄上去,以免以后忘记了,算是做个纪念吧。

#include <string>
#include <iostream>
using namespace std;
void  GetNext(char  str[],int Next[]);
void GetNextval(char  str[],int Nextval[]);
int  KMP(string T,string str,int *Next);
int main(int argc, char* argv[])
{
   
     char  str[]="ababcabcacbab";
  char  str1[]="abcac";
 int  *Next=new  int[strlen(str1)];
 int *Nextval=new  int[strlen(str1)];

  GetNext(str1,Next);
 cout<<"首先得到Next的值:"<<endl;
  for(int i=0;i<strlen(str1);i++)
    cout<<Next[i]<<",";
  cout<<"\n进行KMP的字符串匹配后,得到了字串跟模式串匹配的字符串所在位置:\n";
   cout<<KMP(str,str1,Next)<<endl;

 cout<<"修正得到Next的值:"<<endl;
  GetNextval(str1,Nextval);
for(int p=0;p<strlen(str1);p++)
    cout<<Nextval[p]<<",";
cout<<"\n"<<KMP(str,str1,Nextval);

 return 0;
}
//得到Next的值
void GetNext(char str[],int Next[])
{
 string Str1=str;
 int  j=-1,i=0;
    Next[0]=-1;    
while(i<Str1.length()-1)
{
 if(j==-1||str[i]==str[j])
 { 
  i++;
      j++;
       Next[i]=j;
    }
  else  
     j=Next[j];
}
cout<<endl;
}
//经过修正后的Next函数
void GetNextval(char str[],int Nextval[])
{
  string  Str1=str;
  int j=-1,i=0;
  Nextval[0]=-1;
  while(i<Str1.length()-1)
  {
     if(j==-1||str[i]==str[j])
  {
        i++;
  j++;
  if(str[i]!=str[j])
  {
   Nextval[i]=j;
  }
  else 
   Nextval[i]=Nextval[j];
  }
  else 
         j=Nextval[j];

  }

cout<<endl;
}
//进行模式串的匹配
int KMP(string T,string str,int *Next)
{
 int  i=0,j=0;
  while(i<str.length()&&j<T.length())
  {
    if(str[i]==T[j])
 {
 i++;
 j++;
 }
 else 
 {
  i=Next[i];
     if(i==-1)
  {
   j++;
   i=0; }
 }

return j-i+1;
}

    首先需要知道模式串的匹配,如果要想做到效率高的话,就不能一步一步的往前挪动,

但是对于主串还是一步步往前面指定的元素移动的,只是对于模式串来说就不能每一次都从第一个字符来比较,这样虽然能成功但是效率很低。

就像“000000000000001”和“0001”这两个字符串,如果你一步步的往前面移动,然后遍历

你的模式串,这样的话效率很低,但是当你用了KMP算法后,你这个模式串与主串的比较就只需要11次  ,但是你如果一步步的移动的话,要比较15*4次,这样效率就低了很多。

 

所以KMP算法就发挥了优势,首先需要弄明白的是Next的值,Next的值其实也就是遍历,你从第一个字符开始依次得到每一个字符的Next的值。当你求后面的字符的Next值的时候,需要用到前面的字符的Next的值,这就是KMP不是很好理解的地方。

   上面的代码还修正了Next的值,经过修正的Next的值的效率更高。

原创粉丝点击