KMP算法详解及代码

  • KMP算法详解及代码
    • 定义及应用
    • 理论
      • 基本概念
      • next 数组
      • 总结
      • 注意
    • 代码

KMP算法详解及代码

最近正好在看字符串相关的算法内容,就顺便把KMP算法回顾了一下。相应的代码和联系在下面。

定义及应用

定义:KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。
常见应用场景:在判断某一个字符串中是否出现了另一个字符串的时候。
如我们需要判断:字符串A”adadfhnn“ 是否包含字符串B”adfh“ 的时候就可以使用。
如果按照暴力算法的复杂度就是 A.length * B.length ,需要两层循环。
而我们KMP算法的复杂度只要**(A.length + B.length)**

理论

基本概念

首先我们来看一下正常的暴力算法是怎么进行字符串的匹配的:
我们在字符串A:”ABCABCDHIJK“ 中搜索字符串B:“ABCE”,

在i=3的位置发现不匹配,就会将i指向 0 + 1,j 指向第一个位置 0.如何重新进行挨个匹配。这样的复杂度就是两个字符串长度的积。

然后我们在看一下KMP算法
字符串的索引 i 向前匹配的时候,如果碰到不匹配的字符。我们会考虑,先不改变 i 的位置,直接调整 模式字符串的索引位置 j ,如下图能够发现就算 i 从 第二个位置再和模式字符串按个重新匹配,前两个位置也是匹配不上的。

我们可以直接让从 j 从 第二个位置开始,这样两个字符串就都是从A开始进行匹配了。相当于,i的位置没变,只对 j 的位置进行调整。

而问题的关键就是我们该如果调整 j 的位置。

next 数组

在KMP算法中会先对模式串进行计算。挨个计算不同位置的最大相同前后和缀

**前缀:**前缀就是指一个字符串中除了最后一个字符外,从前往后所有的字符串。
如:ABAD的前缀就有:A , AB , ABA
**后缀:**同样的道理后缀就是指一个字符串中除了第一个字符外,从后往前所有的字符串。
如:ABAD的前缀就有:D , AD , BAD

而next数组就算记录 ABAD中的每个位置的最大相同前后和缀长度。
当 计算第一个位置的值是 A,就一个字符所以没有前后缀,肯定就是 0 ,
当 计算第二个位置的值是 AB,前缀为A,后缀为B,前后缀不相等,所以没有最大相同前后和缀 ,长度也为0
当 计算第三个位置的值是 ABA,前缀有A,AB ;后缀有A ,BA,所以存在相等的前后缀A ,所以长度为1
当 计算最后一个位置的值是 ABAD,前缀有A,AB ,ABA ;后缀有D,AD,BAD,所以没有最大相同前后和缀 ,长度也为0.
最后计算出来的next数组就是:[0,0,1,0 ]

详细视频可以看一下这个up主的视频,挺详细
KMP算法视频链接

总结

当我们计算出next数组后,回到我们开始匹配的地方

当我们有字符不相等的时候,就会查询这个字符前一个位置在next数组中的值,再由 j 指向该位置。如上图:C 和 D 不相等时,就查前面第三个位置在next数组的值:next【2】= 1.
这是时候 i 不动,j 指向 j = 1 ,也就是B的位置,再继续比较就行。

注意

我们在计算next数组的时候通常会有三种不同的取值方式。
[0,0,1,0 ]
[-1,-1,0,-1 ] :全部减一
[0,0,0,1 ] : 全部往右移一位
其实概念是一样的,我们的next数组在取值的时候,会取 j-1 个位置的值,第三中就可以直接取当前j的位置的值,第二种就是会将取到的值加一。其最后得到的都是同一个位置。

###进阶
当我们的模式串为”ABAB“时,我们在匹配的时候,我们会发现当B和C不相等,按照next数组的位置,j 会指向 next[2] = 1. 这时候 j 又指向了B,显然这并没有意义,因为刚刚B和C已经比较过了。所以通常这种情况可以加以判断,如果 sting[ j ] == string[next[j-1]] ,就直接再往前推,j 等于前面这个B前一个位置在next数组中的值。


推荐练习是
Letecode 中的 28. 找出字符串中第一个匹配项的下标。是一道典型的用KMP算法来就行字符串匹配的题目。
这道题的解析:添加链接描述
Letecode 中的 459. 重复的子字符串 是相关的应用,有一点变通。
可以看一下我的解析:
这道题的解析

代码

代码实现(Java):


```java
public int[] setNext(String s) {//将字符串转化成数组。char[] chars = s.toCharArray();//判断字符模式串是否为空。if (s.isEmpty()){return null;}//如果只有一个字符则直接返回数组。if (s.length() == 1){return new int[]{0};}//初始化,j指向第二个字符,因为第一个字符的最长相等前后缀长度一定是0。int j = 1;int i = 0;int[] next = new int[s.length()];next[0] = 0;while (j < s.length()){if (chars[j] == chars[i]){i++;next[j] = i;j++;}else {//如果i和j不相等,则i往前推,让i等于next[i-1]while (i > 0 && chars[j] != chars[i]){i = next[i-1];}//注意这里:需要判断是因为两值相等结束循环的还是i==0,如果此时chars[i] == chars[j],则说明还是有相等前后缀的。if (chars[i] == chars[j]){i++;}next[j] = i;j++;}}return next;}

KMP算法详解及代码相关推荐

  1. KMP算法详解及各种应用

    KMP算法详解: KMP算法之所以叫做KMP算法是因为这个算法是由三个人共同提出来的,就取三个人名字的首字母作为该算法的名字.其实KMP算法与BF算法的区别就在于KMP算法巧妙的消除了指针i的回溯问题 ...

  2. 字符串匹配之KMP算法详解

    kmp算法又称"看毛片"算法,是一个效率非常高的字符串匹配算法.不过由于其难以理解,所以在很长的一段时间内一直没有搞懂.虽然网上有很多资料,但是鲜见好的博客能简单明了地将其讲清楚. ...

  3. KMP算法详解P3375 【模板】KMP字符串匹配题解

    KMP算法详解: KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt(雾)提出的. 对于字符串匹配问题(such as 问你在abababb中有多少个 ...

  4. 粒子群(pso)算法详解matlab代码,粒子群(pso)算法详解matlab代码

    粒子群(pso)算法详解matlab代码 (1)---- 一.粒子群算法的历史 粒子群算法源于复杂适应系统(Complex Adaptive System,CAS).CAS理论于1994年正式提出,C ...

  5. 数学建模——主成分分析算法详解Python代码

    数学建模--主成分分析算法详解Python代码 import matplotlib.pyplot as plt #加载matplotlib用于数据的可视化 from sklearn.decomposi ...

  6. Go-AES算法详解与代码

    目录 AES 发展史 概述 轮函数F 字节代换 行移位 列混淆 轮密钥加 密钥编排 AES和DES的不同之处 分组模式CTR AES的Go实现 aes包 cipher包 加密/解密 参考 本篇介绍分组 ...

  7. 【分享实录】BANCOR算法详解及代码实现

    1 活动基本信息 1)主题:[区块链技术工坊22期]BANCOR算法详解及代码实现 2)议题: BANCOR算法的特点和优劣势 BANCOR算法和举例 如何加入BANCOR.NETWORK交易所 如何 ...

  8. 技术工坊|BANCOR算法详解及代码实现(上海)

    2019独角兽企业重金招聘Python工程师标准>>> EOS项目在RAM分配中采用了Bancor算法,并将RAM的价格爆炒到了很高的价位,凭借EOS项目在区块链领域的强大运营宣传能 ...

  9. 【区块链技术工坊22期实录】王登辉:BANCOR算法详解及代码实现

    1,活动基本信息 1)题目: [区块链技术工坊22期]BANCOR算法详解及代码实现 2)议题: 1)BANCOR算法的特点和优劣势 2)BANCOR算法和举例 3)如何加入BANCOR.NETWOR ...

最新文章

  1. mybatis常见错误
  2. 月份java题_Java基础50道经典练习题(14)——求日期
  3. winSockets编程(二)socket函数
  4. Qt对象类型转换(char* int与Qstring间的转换)
  5. (转)解决在firefox下js调用as失败问题
  6. [导入]防止你的日志页被人iframe
  7. 网页开发浏览器兼容性问题
  8. 怎么改HTML表单数据,form设置的数据怎么添加到table
  9. 基于上下文化图注意力网络的知识图谱的条目推荐
  10. linux源代码剖析之lib
  11. 十五的学习日记20160925
  12. python在电脑下载-Windows下下载及安装numpy、pandas及简单应用
  13. FireBug不能用了?使用火狐Try Xpath插件替代Firebug和Firepath
  14. 计算机图形学 A 课程 专业术语中英对照表
  15. 无线网络的暴力破解密码
  16. 麒麟案例 | 传统企业偶遇“麒麟计划” 相见恨晚 ,却恰逢其时!
  17. 前程无忧招聘信息数据清洗+聚类分析
  18. spring batch的原则(避免停不下来)
  19. LOJ10144宠物收养所
  20. 下载微软官方原版系统镜像

热门文章

  1. 华为交换机重制_华为交换机怎样恢复出厂设置
  2. 麦兜搞it python_一个python程序——聊天
  3. Ubuntu切换到root用户下无法使用java命令,jps用不了--Ubuntu 22.04
  4. html打开图片流,图片网格瀑布流布局和打开图片动画特效
  5. Android Studio实现跳转绘画(简易)
  6. c++入门基础知识——常量和变量
  7. linux mkfifo 命令_linux 中有名管道mkfifo
  8. python中的divmod
  9. C# 多段线 部分或全部分 复制 及 首位相接多段线的拼接。
  10. 数据分析(数据指标+数据工具)