KMP算法前后缀原理

要想把把KMP算法搞清楚,必须要先了解一个叫做BF的暴力破解算法。这个算法的思路相当简单,是在串区配中最容易想到的一个算法。其实就是把所有有可能的串挨个比较一遍,这样匹配的结果一定是正确的。
在这里插入图片描述
如上图所示,T是主串,P是模式串,i是主串T当前的位置,j是模式串P当前的位置,当i=4,j=4时发现T[i]!=P[j],BF算法会将i回溯为1,j回溯为0重新进行下一轮的对比。

下面我们来考虑一个问题,当i=4,j=4检测到字符不相等时,到底有没有必要把i回溯到1、j回溯到0?
把i回溯到1、j回溯到0实际上是为了比较T(1,8)和P是否相等。若能百分之百确定T(1,8)和P不相等,则把i回溯到1、j回溯到0则无意义。可以直接跳过这一轮检测,直接进入下一轮i回溯为2,j回溯为0的检测。
因为T(1,3)是T(1,8)开头的3个字符,P(0,2)是P开头的3个字符。所以:
若T(1,3)不等于P(0,2),则T(1,8)则必不等于P,所以直接跳过i回溯到1、j回溯到0这一步。
若T(1,3)等于P(0,2),则T(1,8)有可能等于P,这一步不能跳过,还得继续比较。又因为前三个字符已经确定是相等的,所以不必从i=1,j=0开始比较,而是可以直接从i=4,j=3开始比较。
所以整个问题的关键就在于T(1,3)到底和P(0,2)相不相等。
又因为T(1,3)等于P(1,3),所以这个问题可以可以转化为比较P(1,3)和P(0,2)相不相等。P(1,3)其实就是P(0,3)长度为3的后缀,P(0,2)其实就是P(0,3)的长度为3的前缀。所以我们有如下结论:
当i=4,j=4检测到字符不相等时,若P长度为3的前缀和后缀相等,则i保持不变,j回溯至3即可。若不等,则整个串也必不匹配,可以跳过此次回溯。
同理我们可以得出:
当i=4,j=4检测到字符不相等时,若P长度为2的前缀和后缀相等,则i保持不变,j回溯至2即可。若不等,则整个串也必不匹配,可以跳过此次回溯。
当i=4,j=4检测到字符不相等时,若P长度为1的前缀和后缀相等,则i保持不变,j回溯至1即可。若不等,则整个串也必不匹配,可以跳过此次回溯。
当i=4,j=4检测到字符不相等时,若P不存在任何长度相等的前缀和后缀相等,则i保持不变,j回溯至0即可。

下面我们不举特殊的例子,直接推导:
假设T的长度是m,P的长度是n
当匹配到第一个不相等的字符时,根据暴力破解法,实际上进行了如下操作:

int k = j - 1;
while (k > 0) {
	把T从i - k开头的位置重新和P比较
	注意此时P(j - k, j - 1)等于T(i - k, i - 1)必相等。
	若此时P(0, j - 1)的长度为k的前缀和后缀相等,P(0,k - 1)P(j - k, j - 1)相等,
	则P(0, k - 1)等于T(i - k, i - 1),
	这就意味着T(i - k, i - k + n)和P前k个字符是相等的,
	所以不需要再比较了,我们可以直接比较T(i - k + k, i - k + k + n)P(k, n - k + 1)即可,
	也就是比较T(i,i+n)P(k,n-k+1)。所以i保持不变,j回溯至k。
	
	若此时P(0, j - 1)的长度为k的前缀和后缀相等,P(0,k - 1)P(j - k, j - 1)不相等,
	则P(0, k - 1)不等于T(i - k, i - 1),
	这就意味着T(i - k, i - k + n)和P前k个字符不相等。
	所以将i回溯至i-k重新比较一遍无意义。
	
	k--;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值