KMP算法详解及代码
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算法详解及代码相关推荐
- KMP算法详解及各种应用
KMP算法详解: KMP算法之所以叫做KMP算法是因为这个算法是由三个人共同提出来的,就取三个人名字的首字母作为该算法的名字.其实KMP算法与BF算法的区别就在于KMP算法巧妙的消除了指针i的回溯问题 ...
- 字符串匹配之KMP算法详解
kmp算法又称"看毛片"算法,是一个效率非常高的字符串匹配算法.不过由于其难以理解,所以在很长的一段时间内一直没有搞懂.虽然网上有很多资料,但是鲜见好的博客能简单明了地将其讲清楚. ...
- KMP算法详解P3375 【模板】KMP字符串匹配题解
KMP算法详解: KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt(雾)提出的. 对于字符串匹配问题(such as 问你在abababb中有多少个 ...
- 粒子群(pso)算法详解matlab代码,粒子群(pso)算法详解matlab代码
粒子群(pso)算法详解matlab代码 (1)---- 一.粒子群算法的历史 粒子群算法源于复杂适应系统(Complex Adaptive System,CAS).CAS理论于1994年正式提出,C ...
- 数学建模——主成分分析算法详解Python代码
数学建模--主成分分析算法详解Python代码 import matplotlib.pyplot as plt #加载matplotlib用于数据的可视化 from sklearn.decomposi ...
- Go-AES算法详解与代码
目录 AES 发展史 概述 轮函数F 字节代换 行移位 列混淆 轮密钥加 密钥编排 AES和DES的不同之处 分组模式CTR AES的Go实现 aes包 cipher包 加密/解密 参考 本篇介绍分组 ...
- 【分享实录】BANCOR算法详解及代码实现
1 活动基本信息 1)主题:[区块链技术工坊22期]BANCOR算法详解及代码实现 2)议题: BANCOR算法的特点和优劣势 BANCOR算法和举例 如何加入BANCOR.NETWORK交易所 如何 ...
- 技术工坊|BANCOR算法详解及代码实现(上海)
2019独角兽企业重金招聘Python工程师标准>>> EOS项目在RAM分配中采用了Bancor算法,并将RAM的价格爆炒到了很高的价位,凭借EOS项目在区块链领域的强大运营宣传能 ...
- 【区块链技术工坊22期实录】王登辉:BANCOR算法详解及代码实现
1,活动基本信息 1)题目: [区块链技术工坊22期]BANCOR算法详解及代码实现 2)议题: 1)BANCOR算法的特点和优劣势 2)BANCOR算法和举例 3)如何加入BANCOR.NETWOR ...
最新文章
- mybatis常见错误
- 月份java题_Java基础50道经典练习题(14)——求日期
- winSockets编程(二)socket函数
- Qt对象类型转换(char* int与Qstring间的转换)
- (转)解决在firefox下js调用as失败问题
- [导入]防止你的日志页被人iframe
- 网页开发浏览器兼容性问题
- 怎么改HTML表单数据,form设置的数据怎么添加到table
- 基于上下文化图注意力网络的知识图谱的条目推荐
- linux源代码剖析之lib
- 十五的学习日记20160925
- python在电脑下载-Windows下下载及安装numpy、pandas及简单应用
- FireBug不能用了?使用火狐Try Xpath插件替代Firebug和Firepath
- 计算机图形学 A 课程 专业术语中英对照表
- 无线网络的暴力破解密码
- 麒麟案例 | 传统企业偶遇“麒麟计划” 相见恨晚 ,却恰逢其时!
- 前程无忧招聘信息数据清洗+聚类分析
- spring batch的原则(避免停不下来)
- LOJ10144宠物收养所
- 下载微软官方原版系统镜像
热门文章
- 华为交换机重制_华为交换机怎样恢复出厂设置
- 麦兜搞it python_一个python程序——聊天
- Ubuntu切换到root用户下无法使用java命令,jps用不了--Ubuntu 22.04
- html打开图片流,图片网格瀑布流布局和打开图片动画特效
- Android Studio实现跳转绘画(简易)
- c++入门基础知识——常量和变量
- linux mkfifo 命令_linux 中有名管道mkfifo
- python中的divmod
- C# 多段线 部分或全部分 复制 及 首位相接多段线的拼接。
- 数据分析(数据指标+数据工具)