KMP算法

昨晚一直在啃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开始计,所以要加1
	else 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] ]就是应该回溯的位置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值