再玩KMP算法

  廢話少說,我把代碼弄上去,以免以後忘記了,算是做個紀念吧。

#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的值的效率更高。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章