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

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

前言


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


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


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


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


      其余篇章将在之后更新


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


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


前情提要:


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


数理篇正式开始:



0
1 2 3 4 5 6 7 8 9 10
PAT字符串 a b c a b a b c a b c
NEXT数组 -1 0 0 0 1 2 1 2 3 4 5


现在有这样一个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从哪里来的呢?


f59e6bf8d60343309b54b898fe3a1582.jpg


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。


f59e6bf8d60343309b54b898fe3a1582.jpg


那如果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。

2e41650292bb4bc5aed5b7783afdcb2e.jpg


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


05144020fdb7427f9e164c321bcb1ac1.jpg


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


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


诸君,山顶见!


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

目录
相关文章
|
15天前
|
存储 算法
图解Kmp算法——配图详解(超级详细)
图解Kmp算法——配图详解(超级详细)
|
20天前
|
算法 测试技术 C#
【字典树】【KMP】【C++算法】3045统计前后缀下标对 II
【字典树】【KMP】【C++算法】3045统计前后缀下标对 II
|
20天前
|
算法
【算法学习--字符串】(不含KMP算法)
【算法学习--字符串】(不含KMP算法)
|
2月前
|
算法
白话 KMP 算法
白话 KMP 算法
14 2
|
2月前
|
算法 Java 索引
算法基础:KMP算法详细详解
算法基础:KMP算法详细详解
|
3月前
|
算法 测试技术 C++
【KMP】【二分查找】【C++算法】100207. 找出数组中的美丽下标 II
【KMP】【二分查找】【C++算法】100207. 找出数组中的美丽下标 II
|
3月前
|
算法
KMP 算法小结
KMP 算法小结
11 0
|
10天前
|
机器学习/深度学习 人工智能 算法
基于DCT和扩频的音频水印嵌入提取算法matlab仿真
本文介绍了结合DCT和扩频技术的音频水印算法,用于在不降低音质的情况下嵌入版权信息。在matlab2022a中实现,算法利用DCT进行频域处理,通过扩频增强水印的隐蔽性和抗攻击性。核心程序展示了水印的嵌入与提取过程,包括DCT变换、水印扩频及反变换步骤。该方法有效且专业,未来研究将侧重于提高实用性和安全性。
|
25天前
|
机器学习/深度学习 算法
【MATLAB】GA_BP神经网络时序预测算法
【MATLAB】GA_BP神经网络时序预测算法
35 8
|
1天前
|
算法 TensorFlow 算法框架/工具
基于直方图的图像阈值计算和分割算法FPGA实现,包含tb测试文件和MATLAB辅助验证
这是一个关于图像处理的算法实现摘要,主要包括四部分:展示了四张算法运行的效果图;提到了使用的软件版本为VIVADO 2019.2和matlab 2022a;介绍了算法理论,即基于直方图的图像阈值分割,通过灰度直方图分布选取阈值来区分图像区域;并提供了部分Verilog代码,该代码读取图像数据,进行处理,并输出结果到"result.txt"以供MATLAB显示图像分割效果。