KMP算法的基础应用

KMP算法的基础应用

本篇博客来源于https://www.cnblogs.com/yjiyjige/p/3263858.html,内容中含有大量原文,仅是本蒟蒻的一篇笔记
KMP算法指的是字符串模式匹配算法,问题是:在主串T中找到第一次出现完整子串P时的起始位置。该算法是三位大牛:D.E.Knuth、J.H.Morris和V.R.Pratt同时发现的,以其名字首字母命名。本篇博客讲介绍KMP算法的最基础应用。

一般字符串匹配问题的解法:

对于这种字符串匹配问题,通常的思路是一个一个字母的匹配直到完全重合,如果不匹配则将下面的关键字向右移动一位,直到遍历所有或者找到完全匹配的字符串。

显然这很暴力。比如,对于串“SSSSSSSSSS”和串“SB”来讲,我们要找到最后才能得到答案,即没有与之匹配的串。大牛忍受不了这种低效暴力的算法,一起研究出了KMP算法,整个算法的核心就是利用已经“部分匹配”的信息,更快找到答案。所以,整个KMP的重点就在于当某一个字符与主串不匹配时,我们应该知道j指针要移动到哪?

接下来我们自己来发现j的移动规律:

如图:C和D不匹配了,我们要把j移动到哪?显然是第1位。为什么?因为前面有一个A相同啊:
在这里插入图片描述
在这里插入图片描述

如下图也是一样的情况:
在这里插入图片描述

可以把j指针移动到第2位,因为前面有两个字母是一样的:
在这里插入图片描述

至此我们可以大概看出一点端倪,当匹配失败时,j要移动的下一个位置k。存在着这样的性质:最前面的k个字符和j之前的最后k个字符是一样的。如果用数学公式来表示是这样的
P[0 ~ k-1] == P[j-k ~ j-1]

该规律是KMP算法的关键,KMP算法是利用待匹配的子串自身的这种性质,来提高匹配速度。该性质在许多其他中版本的解释中还可以描述成:若子串的前缀集和后缀集中,重复的最长子串的长度为k,则下次匹配子串的j可以移动到第k位(下标为0为第0位)。我们将这个解释定义成最大重复子串解释。
这里面的前缀集表示除去最后一个字符后的前面的所有子串集合,同理后缀集指的的是除去第一个字符后的后面的子串组成的集合。举例说明如下:
在“aba”中,前缀集就是除掉最后一个字符’a’后的子串集合{a,ab},同理后缀集为除掉最前一个字符a后的子串集合{a,ba},那么两者最长的重复子串就是a,k=1;
在“ababa”中,前缀集是{a,ab,aba,abab},后缀集是{a,ba,aba,baba},二者最长重复子串是aba,k=3;
在“abcabcdabc”中,前缀集是{a,ab,abc,abca,abcab,abcabc,abcabcd,abcabcda,abcabcdab},后缀集是{c,bc,abc,dabc,cdabc,bcdabc,abcdabc,cabcdabc,bcabcdabc},二者最长重复的子串是“abc”,k=3;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值