KMP算法思想介绍

KMP算法思想介绍

KMP算法是解决字符串匹配问题的很高效的一种算法,它的总的设计思想是当在某一个位置出现不匹配的字符时,应尽量向右移动尽可能大的距离,避免重复比较。

暴力算法

从主串和模式串(带匹配字符串)的第一个字符开始,依次进行比较,当出现不匹配的字符时,模式串位置向后移动一位,在从模式串的第一个字符开始依次与对应的主串字符比较。重复这个过程直到匹配成功或者未找到匹配位置。

最坏情况的时间复杂度o(n*m)

KMP算法:

时间复杂度可以达到o(m+n)

下面来叙述KMP算法的过程:

如图所示,给出了主串和模式串:

在这里插入图片描述

第0个字符开始匹配,直到第3个字符出现了不匹配:
在这里插入图片描述

这时如果按照暴力算法,模式串应该往后移动一个位置,在重新开始匹配:
在这里插入图片描述

但是追求效率的工程师并不会这样做,因为这样的效率太低了。按照KMP算法的思路,直接移动两个位置:
在这里插入图片描述

为啥可以这样做呢?因为我们已经观察到,第3个字符开始出现不匹配,说明前0 1 2 的3个字符是匹配的,即主串的第0 1 2个字符与模式串的第0 1 2个字符一样。

但是一样又有什么卵用呢?

接下来就是KMP算法的内核了:

先把不匹配字符前面的字符串提取出来:ABA

然后定义不匹配字符前面的字符串的前缀字符串为:A AB

定义不匹配字符前面的字符串的后缀字符串为: A BA

(考虑到此处可能有歧义,再次说明下,比如不匹配字符前面的字符串为ABCDEF,则前缀字符串是A,AB,ABC,ABCD,ABCDE,后缀字符串是F,EF,DEF,CDEF,BCDEF。)

然后发现前缀字符串与后缀字符串中相等的最大字符串为A,所以接下来只需移动模式串使它们重合就可以:

在这里插入图片描述

如图,标红的就是最大相等前后缀字符串。如果还不明白,再来一个例子,比如对于ABCBABC,
自己写出来前缀字符串与后缀字符串,会发现前后缀相等的最大字符串是ABC)

我们已经知道了如何操作,但是原理是什么呢?可以仔细想想,当匹配失败时,按照暴力算法,要移动一个位置,从模式串第一个字符重新开始比较,这时不就相当于比较不匹配字符前面的字符串的前缀字符串与后缀字符串吗,所以当前位置不是前后缀相等的最大字符串时,你的工作都白做了,这正是暴力算法的缺陷所在,把已经知道的信息重复获取,效率很低。

因此KMP算法的一个改进就是引入next函数,将模式串预处理,注意到每次不匹配时要移动的距离只和模式串本身以及不匹配字符在模式串中的位置有关(因为前后缀字符串只与它们有关),所以对于上述例子,我们有:
在这里插入图片描述
其中j代表不匹配字符在模式串中的位置,next(j)表示如果不匹配字符是这个位置,那么下次直接拿模式串的第next(j)个位置的字符与主串不匹配位置的字符比较。

KMP的核心就是预处理next函数的实现。本质上,KMP使用的是贪心策略,即寻找相等的最大前后缀字符串。

理解了KMP的核心,代码实现也就简单了,只要注意边界与下标,另外j=0的情况即可。

代码在任一文章或者教科书上都有,在此不再写了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值