KMP算法

来源:互联网 发布:淘宝怎么提升5星好评 编辑:程序博客网 时间:2024/05/29 03:42

昨晚一直在啃KMP,总算是对这个久仰的算法有了大概的了解。

KMP(字符串匹配)算法对于初学者来说肯定是一块难啃的骨头(这个比喻真无聊=_=)

为了理解这个精妙的算法,我参考了以下博客:

http://www.matrix67.com/blog/archives/115   matrix67大牛的KMP讲解,在网上看KMP的基本都看过吧。。。

http://chaoswork.com/blog/2011/06/14/kmp%E7%AE%97%E6%B3%95%E5%B0%8F%E7%BB%93/  这篇文章条理很清晰

还有新买的《大话数据结构》等等,图文并茂,他们总结得很好,很适合初学者。


下面是我自己根据书上的代码修改而来的包含测试用例的KMP算法:


#include <iostream>//KMP TEST#include <string>using namespace std;int Next[1001];//next 数组void getNext(const string &str){int len=str.length();int i=1,j=0;Next[i]=j;while(i<len){if ( j==0 || str[i-1]==str[j-1] )//这里很需要注意,因为字符串第一个下标是0不是1,需要减1,很多算法书抄来抄去而没有指明这一点(下同){i++;j++;Next[i]=j;}else j=Next[j];//回溯到上一个匹配的位置}}int index_KMP(const string &S,const string &T,int pos)//返回子串T在主串S中第Pos个字符之后的位置{int i=pos,j=0;int slen=S.length() , tlen=T.length();getNext(T);//调用上面的getNext函数while( i<slen && j<tlen ){                     if( j==0 || S[i-1]==T[j-1] )  { i++; j++;}//根据Next数组实行回溯或者进行下一次比较else j=Next[j];}if(j>=tlen ) return i-tlen+1;//这里是返回第四个,因为字符串从0开始计,所以要加1else return -1;//表示不存在}int main(){string str1("qweabcaabxasd"),str2("abcaabx");int index;index=index_KMP(str1,str2,0);//获取下标if(index==-1) cout<<"Can not find the word"<<endl;else cout<<"Yeap! The word display in the index of "<<index<<endl;cout<<endl;return 0;}
可以说,KMP算法的关键是求出Next数组,那么,为什么需要这个数组呢。

我的理解:为了在子串在与主串比较中不相等时, j回溯到哪个位置,或者说子串向右移动多少位。

而Next数组是根据子串的结构的自我匹配而生成的,说白了就是先给自己标记一下,哪些地方是可以跳过比较的,这就是Next数组存在的意义,

也就是KMP比朴素字符串匹配的优越之处。

然而我还不太清晰的是,为什么Next[ Next[j] ]就是应该回溯的位置。

原创粉丝点击