KMP算法简介——附代码解析

KMP算法是由一个问题而引发的:对于一个字符串 str (长度为N)和另一个字符串 match (长度为M),默认N≥M。如果
match 是 str 的子串,请返回其在 str 第一次出现时的首字母下标,若 match 不是 str 的子串则返回 -1 。

子序列:可以连续,也可以不连续,比如ac1de,abc123
子串/子数组:必然连续
二者有时候是混用的!

getIndexOf 方法:
即getIndexOf (str1,str2)返回一个整型
若match 是 str 的子串,返回其在 str 第一次出现时的首字母下标;
如果不是,则返回-1

最简单的方法是将 str 从头开始遍历并与 match 逐次比较,若碰到了不匹配字母则终止此次遍历转而从 str 的
第二个字符开始遍历并与 match 逐次比较,直到某一次的遍历每个字符都与 match 匹配否则返回 -1 。
易知此种做法的时间复杂度为 O(N*M) 。

KMP算法则给出求解该问题时间复杂度控制在 O(N) 的解法
原理:让前面配过的指导后面。
在这里插入图片描述
举例说明:
在这里插入图片描述
对于这样一个字符串
前缀取1,后缀取1,两者不等。
在这里插入图片描述
前缀取2.后缀取2,两者不等。
在这里插入图片描述
前缀取3.后缀取3,两者相等。
在这里插入图片描述
前缀取4后缀取4,两者不等。
在这里插入图片描述
前缀取5后缀取5,两者不等。
在这里插入图片描述
前缀取6后缀取6,两者相等。
但是!
不能要这一种情况!
所以d位置上的 最长前缀和最长后缀的匹配长度为3

再举一个例子:
求b前面的最长前缀和最长后缀的匹配长度
在这里插入图片描述

在这里插入图片描述
注意长度不能取5!
前缀不能取最后一个数,后缀 不能取到最前面的数
长度为4是最长的,所以b位置上的最长前缀和最长后缀的匹配长度为4

假设str2字符
在这里插入图片描述
我们求其中每一个数的 最长前缀和最长后缀的匹配长度
并且将值 返回一个数组
表示 每一个位置上 前面字符串的 最长前缀和最长后缀的匹配长度

0位置在前面过程中,没有字符串,所以默认-1;
1位置,即b,前面只有一个字符,我们强调过,前缀不能取最后一个数,后缀 不能取到最前面的数,人为规定 为0
2位置,即a,前面有两个字符,若这两个字符,相等,则为1;不等则为0!
最后结果:
在这里插入图片描述
假设两字符串一路都相等,直到x y
在这里插入图片描述
在这里插入图片描述
这时我们得到 y位置的 最长前缀和最长后缀(存放于next数组)
在这里插入图片描述
举个例子:

在这里插入图片描述
之前 算法。,t若与a不能匹配,则 :

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
接下来比较这两者是否相等!
在这里插入图片描述
清晰一点的图如下:
在这里插入图片描述
another 例子:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
解释完过程,我们来看为何这么做,即这么做的实质:

在这里插入图片描述
在举个例子:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
连续配两次
在这里插入图片描述
此时,以及没有办法再推了
在这里插入图片描述
如果最长前、后缀都没了,那么两个要统一换!

即 str1的下一个字符与str2 的0位置 互换!
在这里插入图片描述
往后推的含义:
乙指针指向 最长前缀和最长后缀的匹配长度所在的位置
在这里插入图片描述
我们以这个a位置和str1的甲位置开始匹配!
在这里插入图片描述
我们认为从i位置到j位置一律配不出str2。这是这件事情的实质!

Y之前 最长前、后缀字符串的 长度为:
在这里插入图片描述
将其放入next数组。

之前 讲到,推的实质是,j位置上的数,和0位置的数开始比较,只是因为前面一样,所以才从 此处开始 比较
在这里插入图片描述
我们认为,i位置和j位置之间,任意某个位置k,从k位置出发,是配不出整个str2的
在这里插入图片描述
为了证明上句话,我们可以假设可以配出
在这里插入图片描述
而这三者是一样的!
在这里插入图片描述

在这里插入图片描述
主方法代码:

在这里插入图片描述
接下来看getNextArray函数:
在这里插入图片描述
假设i位置之前 已经求解了所有next数组的值,如何求i位置上的呢?

假设i-1位置上的数,返回值为4,为了求i位置上的,我们就看 长度为4位置上的 下一个字符i位置前面的字符,比较两个数是否相同
若相同,则i位置上的数,在i-1的基础上加1.
在这里插入图片描述
若不同:
在这里插入图片描述
此时,i-1的长度为5,比较这俩是否相同
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
若这时对上了,则n位置的长度为 cn位置上数+1 !

举例:

此时,t≠c;则将c的最长前缀和最长后缀分为两坨,然后 取其 最长前缀的后一个数和t比较!
在这里插入图片描述
a≠t,a不能继续往前分两坨了,所以k的最长前缀和最长后缀的匹配长度为0
在这里插入图片描述
若t变为a
在这里插入图片描述
因为c 的前缀长度为2,所以k就为3!
在这里插入图片描述
分析:最长确实是 aba,aba
在这里插入图片描述
代码分析:
在这里插入图片描述
cn是指 要跳到的位置!
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
进阶1 刚开始

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是通过一个next()函数实现,函数本身包含了模式串的局部匹配信息。KMP算法的时间复杂度为O(m+n)。\[2\] 下面是一个使用KMP算法的C语言代码示例: ```c int KMP(char *chang, char *duan) { int c_strlen = strlen(chang); int d_strlen = strlen(duan); int c = 0, d = 0; while (c < c_strlen && d < d_strlen) { if (chang\[c\] == duan\[d\]) { c++; d++; } else { d = Next\[d\]; // 失配,指针回退到对应Next\[\]下标元素。 } } return d < d_strlen ? -1 : c - d; } ``` 在这段代码中,`chang`表示主串,`duan`表示模式串。算法通过比较主串和模式串的字符来进行匹配,当字符不匹配时,根据`Next`数组的值来决定模式串的指针回退位置。如果模式串完全匹配成功,则返回匹配的起始位置;否则返回-1。\[3\] 需要注意的是,代码中的`Next`数组没有给出具体实现,你需要根据KMP算法的原理来计算并填充`Next`数组。 #### 引用[.reference_title] - *1* [【详解】KMP算法——多图,多例子(c语言)](https://blog.csdn.net/Zero__two_/article/details/120334582)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [字符串匹配——KMP算法【C语言】](https://blog.csdn.net/weixin_45423515/article/details/124232548)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值