KMP算法

KMP算法需要提前求匹配模式串的前缀函数。这个前缀函数的定义是:一个字符串的真前缀,并且这个真前缀是该字符串的后缀,并且要求这个真前缀是符合这种条件中最长的真前缀。

原文对前缀函数的描述是:That is, Pi[q] is the length of the longest prefix of P that is a proper suffix of Pq.

在应用字符串匹配过程中,这个前缀函数起到的作用是,当匹配过程中发现不一致时,整个字符串不需要仅仅往后移一个字符来比较,而是可以往后移动若干个字符,因为根据前缀函数,我们可以得知已经匹配的模板子串中的前缀和后缀相同的部分,所以,可以直接把已匹配的子串的前缀放到子串的后缀部分即可,再进行后边的比较。

根据算法导论中的伪代码改编成如下代码:

int* computePrefixFunction(const string &P)
{
	int m = P.length();
	int *pi = new int[m];
	pi[0] = -1;
	int k = -1;            //k表示第0个之前的数
	for(int q = 1; q < m; ++q)
	{
		while( k > -1 && P[k+1] != P[q])
			k = pi[k];
		if(P[k+1]==P[q])
			k = k + 1;
		pi[q] = k;
	}
	return pi;
}

void kmpMatching(const string &T, const string &P)
{
	int n = T.length();
	int m = P.length();
	int *pi = computePrefixFunction(P);
	int q = -1;                 //number of characters matched - 1
	for(int i = 0; i < n; ++i)  //scan the text
	{
		while(q >= 0 && P[q+1] != T[i])
			q = pi[q];          //next character does not match  
		if(P[q+1] == T[i])
			q = q + 1;          //next character matches 
		if(q == m-1){           //is all of P matched? 
			cout << "Pattern occurs with shift" << i - m <<endl;
			q = pi[q];          //look for the next match
		}
	}
	delete [] pi;
}

算法导论的伪代码中的字符串都是从1开始,我修改为从0开始,可能对代码的可读性造成一些影响。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值