KMP算法

朴素的字符串匹配算法:

文本串text[]和模式pattern[]匹配,自然的想法是O(n^2)算法,拿pattern[]的字符从头到尾和text[]匹配,设i为text[]当前下标,j为pattern[]当前下标,每一次text[i] != pattern[j],下标j将重新归0,i加一,然后重复。

int Brute_Force(){
	int i=0, j=0;
	int m = strlen(text);
	int n = strlen(pattern);
	while(i<m && j<n){
		if(text[i] == pattern[j]){
			++i; ++j;
		}
		else{
			i -= (j-1); j = 0;
		}
	}
	//... 
}

KMP算法:

观察上面的BF算法,不难发现每次匹配失败,j都要重置为0。KMP算法改进了BF算法,使得j不需要每次都重置为0.
kmp算法的思想:
倘若text[]和pattern[]能局部匹配,那么当某次匹配失败时(设text[]此时下标为i, pattern[]下标为j),pattern[j] != text[i], 那么我们可以知道, text[i]左边的若干个连续字符和pattern[]匹配,同时我们可以想象,pattern[]相对于text[]右移若干个单位长度,即可以使得pattern[]和text[]重新匹配。我们有需要如下的几个条件:
(1)pattern[0, j) == text[ i-j, i)     即失配位置的左边为匹配的。

(2)pattern[0, t) == text[i-j, i)      即pattern相对于text右移了j-t个单位后,使得pattern[]和text[]重新匹配。

(3)pattern[j-t, j) == text[i-j, i)     这点联系第一点不难得知。

(4)于是, 对比(2),(3)我们得到:pattern[0, t) == pattern[j-t, j) 。 即在pattern[0, j)中长度为t的真前缀,要和长度为t的后缀完全匹配。

(5)观察加想象,为了保证pattern[]右移(j-t)个长度不遗漏任何情况,我们应该使得j-t尽可能的小,即t尽可能的大。

(6) 失配后的下一次匹配位置是pattern[t]

到目前为止,实现kmp算法还需要求解t的值。再观察以上得到的结论,我们发现, t值和text[]无关! 求t值现在转换成了求pattern[0, j)最长真前缀和最长真后缀,且真前缀和真后缀完全匹配(相同)。进一步,我们顺其自然的知道,可以先预处理出t的值,之后重复使用即可。我们将t的值写在一个next[]数组里。

求next[]:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值