九分钟带你弄懂KMP算法【数理篇】

该文章详细解析了KMP算法中的核心部分——NEXT数组,分为原理、数理和实现三个阶段。在数理篇中,作者通过两个指针i和k,解释了如何根据字符串的匹配关系推导NEXT数组的构建规律,包括当PAT[i]=PAT[k]和PAT[i]≠PAT[k]两种情况下的处理方式,为算法的高效实现奠定了基础。
摘要由CSDN通过智能技术生成

前言

        我将KMP算法的详解分为三个篇章:

         【原理篇】:主要讲解KMP实现的原理,以及手动求NEXT数组。

      ->【数理篇】:主要讲解如何在手动求出NEXT数组的情况下,找出数学规律,为之后的算法实现奠定基础。

         【实现篇】:主要讲解以C语言代码的方式实现KMP算法,以及NEXT数组的优化。

        其余篇章将在之后更新

🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈

  制作不易,若对你有帮助的话点赞、关注、评论走一波,你们的支持是我前进路上最大的动力。

前情提要:

        在原理篇当中我已经讲解了KMP中最核心的NEXT数组,以及他的求法:NEXT[j]存储了从PAT[0]到PAT[j-1]位置,以PAT[0]为首,PAT[j-1]为结尾的两个最长子字符串的长度位(可以重叠,但不能相等)。忘记的朋友们可以看看之前的篇章。

数理篇正式开始:

012345678910
PAT字符串abcababcabc
NEXT数组-10001212345

现在有这样一个NEXT数组,除了NEXT[0]与NEXT[1]是已经规定好的-1和0之外,其余的都要我们手动去求。在上一个篇章当中,我们学会了如何用手去求NEXT数组。但在实际生产过程当中,这种方法肯定是不可取的,那么NEXT数组的构成当中有什么规律呢

我们先假设在NEXT数组当中,有两个指针,一个叫i一个叫k。

设有NEXT[i]=k,也就是可以通过NEXT数组的下标去访问K指针所在的位置,这一假设是以下的推论的大前提。

此时就有p[0]--p[k-1](以首元素为头的子字符串)=p[x]--p[i-1](以i-1为尾的子字符串)这两个字符串相同,疑惑为什么相同的朋友们可以去看看NEXT数组的定义。那这里的X从哪里来的呢?

x是为了之后的推导,先假设出来的,如果不解继续往下看~

因为两字符串长度相同(定义),所以就存在关系 k-1-0=i-1-x,也就可以推导出x=i-k

此时再将x放回上文的推导关系,就有这样的一个关系p[0]--p[k-1]=p[i-k]--p[i-1]

情况1:PAT[i]=PAT[K]

当PAT[i]=PAT[K]时,也就是对应的两个字符相同,可以参考上图中i k对应的位置。又因为

p[0]--p[k-1]=p[i-k]--p[i-1],p[i]=p[k](字符相同),所以就有p[0]--p[k]=p[i-k]--p[i],

又因为从next[i]=k可以推导出p[0]--p[k-1]=p[i-k]--p[i-1],那么是不是p[0]--p[k]=p[i-k]--p[i]可以反向推导出next[i+1]=k+1!

那么也就可以得出情况一的结论:

在PAT[i]=PAT[k]的情况下,NEXT[i+1]=k+1。

那如果PAT[i]!=PAT[k]呢?那这就是我们的情况2

情况2:PAT[i]!=PAT[K]

那就非常简单粗暴了,k=NEXT[k],也就是一直往回退直到满足PAT[i]=PAT[k]这一情况时,在继续套用情况一进行推导。如图,此时PAT[i]!=PAT[K],那么,就令k=NEXT[k],也就是移动到,p[0]的位置,此时满足情况1PAT[i]=PAT[K],所以此时的NEXT[i+1]=k+1,也就是NEXT[4]=1。

 若退回到0位置时还不相等呢?那继续往下退到-1岂不是越界了?这里可以加一个判定,若退到0还不满足,可以直接令NEXT[i+1]=0(-1+1),具体实现可以关注我下一篇KMP代码实现的讲解。

 

至此,本篇博客的内容九分钟带你弄懂KMP算法【数理篇】告一段落,若对你有些许帮助,可以点赞、关注、评论支持下博主,你的支持将是我前进路上最大的动力。

若以上内容有任何问题,欢迎在评论区指出。若对以上内容有任何不解,都可私信评论询问。

诸君,山顶见!

🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈​​​​​​​

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
KMP算法(Knuth-Morris-Pratt算法)是一种字符串匹配算法,用于在一个文本串S中查找一个模式串P的出现位置。它的核心思想是利用已经匹配过的部分字符,尽量减少不必要的比较次数。 KMP算法的步骤是这样的: 1. 预处理模式串P,得到一个next数组。next[i]表示P[0:i]这个子串中,最长的相等前缀和后缀的长度。我们可以通过不断比较P的前缀和后缀得到这个next数组。 2. 遍历文本串S,同时遍历模式串P。当遇到不匹配的字符时,根据next数组,将模式串P向右移动尽量少的距离。移动的距离由next数组中的值决定。 3. 当P移到最右端时,如果还是没有匹配成功,则继续将P向右移动一个位置,继续匹配。 这样,通过预处理模式串P,我们能够在匹配过程中尽量少的进行字符比较,提高了算法的效率。 终于全部弄懂KMP算法,我明白了它的原理和实现过程。它的核心在于构建next数组,这个数组能够帮助我们在匹配过程中避免重复比较已经匹配过的字符。通过next数组,我们可以事先知道模式串P中的每个位置的最长相等前缀和后缀的长度,从而决定每次匹配过程中的移动距离。 KMP算法是一种高效的字符串匹配算法,它的时间复杂度为O(n+m),其中n和m分别是文本串S和模式串P的长度。相比于暴力匹配算法的时间复杂度O((n-m+1)m),KMP算法具有明显的优势。 了解KMP算法的原理和实现,对于我在日常编程中遇到的字符串匹配问题将会更加得心应手。我相信通过不断实践和总结,我能够更加熟练地运用KMP算法,解决字符串匹配相关的挑战。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ppeua

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值