廢話少說,我把代碼弄上去,以免以後忘記了,算是做個紀念吧。
#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的值的效率更高。