KMP算法详解(原理篇)

1 KMP算法是干嘛的?

我们在查找字符串的子串的时候,往往采用暴力匹配的方法进行字符串的匹配。也即,当模式串和字符串不匹配时,就退回到字符串当前匹配的后一个字符,从头开始匹配。这样的时间复杂度为O(m*n)。实在太慢啦!

那么有没有办法可以降低复杂度,最好在字符串上的指针都不用回退的,这样的时间复杂度就可以大大降低!

KMP算法就是干这事儿,它表示爷从来不走回头路

那么,KMP算法是如何做到的呢?

2 KMP算法的整体实现

大名鼎鼎的KMP算法,其实是靠一个小小的next数组来实现的,让我们先抛开next数组怎么来的,先来看看KMP算法的整体实现过程。

By the way, next数组在整体实现中的定义是,当前指针的前一个数组下标对应的值,就是子串可以跳过的步数。

让我们来举个栗子:

我们匹配到C发现行不通,那么就看上一个next数组的元素,是2,那么好,我们直接啪的一声很快,跳过两步:

好家伙,这是不是就匹配上了,神奇吧!

那么next数组是怎么的出来的呢?它又是为什么可以跳过元素呢?

3 Next数组的原理

我们已经知道next数组可以跳过前面的元素,那么这是为什么呢?如果我们仔细观察模式串的数值,就不难发现:实际上跳过的元素个数正是相同的前后缀的长度

更精确地说,Next数组中的数值,正是当前下标与下标0组成的模式子串中,相同前后缀的最大长度。由于后面若干个元素与前面若干个元素相同,因此前面的可以直接跳到后面去!这就是next数组这么能跳的本质!

4 Next数组的计算

知道了Next数组的定义,那么计算出Next数组的值也就顺理成章了。在Next数组的计算中,我们不难发现有两种情况:

4.1 前一个元素相同,下一个元素也相同

毫无疑问,这种情况下,next[i] = next[i - 1] + 1;

4.2 前一个元素相同,下一个元素不相同

这种情况有点棘手,难道我们又要开始暴力回头了吗?不,真男人从不回头,还记得前缀与后缀相同吗?既然整体的后缀已经没办法和前缀相同了,那么一部分的后缀和一部分前缀有没有可能相同呢?

我们可以明显发现,是有可能的,那么从前缀的哪一部分开始匹配呢?我们发现,右边的前后缀其实就等同于左边的前后缀。那么其实等于从左边的相同位置开始查,也就是next[2]的位置。

next[2] = 1,我们能跳一步,从next[1]开始比较。发现相同,那么就next[2]+1=2。如果还不相同,那就再跳,是的还可以跳。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值