KMP算法小结
最近看了一些关于KMP算法的资料,在此写一篇博客总计一下。
1.KMP算法介绍
KMP算法是一种字符串搜索的改进算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。
举个例子:
有两个字符串,我们要在第一个字符串(主串)中寻找第二个字符串(模式串):
bacbabababacaab
ababca
寻找的方法很简单,就是逐位进行比较,要是不相等就把模式串右移。
考虑下面这种情况:
bacbabababacaab
ababaca
绿色的字符串表示匹配的部分,红色的字符串表示不匹配的部分。
此时我们的字符串并没有完全匹配,因此我们需要把模式串往右移。
此时一般的字符串匹配算法会这么做:
bacbabababacaab
ababaca
但这么做就浪费了我们绿色部分匹配所获得的信息。我们可以看到,对于绿色匹配部分,我们拥有两个相同的前缀与后缀:
后缀:ababa
前缀: ababa
因此在这里我们的模式串是可以向右移动两位的:
bacbabababacaab
ababaca
这也就是KMP算法的思想:利用匹配失败后的信息,尽量减少模式串与主串的匹配次数
因此我们会在KMP算法中维护一个next数组,该数组的下标表示了主串与模式串匹配相同的长度(也就是绿色部分字符串的长度,同时也是匹配失败的位置),而数组中则存储了该绿色字符串相同前后缀的长度。因此当我们匹配失败时我们可以移动:绿色字符串长度 - 绿色字符串前后缀长度(如上面的例子就是5 - 3 = 2)
2.KMP算法的实现
- /**
- * 输入模式字符串返回其对应的next数组
- * @param p 模式字符串
- * @return next数组
- */
- private static int[] KMPNext(String p) {
- // 初始化
- int len = p.length();
- int next[] = new int[len];
- next[0] = next[1] = 0;
- for (int i = 1; i < len-1; i++) {
- int j = next[i]; // 相同前缀的最后一位字符
- while (j > 0 && p.charAt(i) != p.charAt(j)) // 如果第i位字符与前缀最后一位字符不相等,则去寻找前缀的前缀,如果没有前缀则退出循环
- j = next[j];
- if (p.charAt(i) == p.charAt(j)) // 如果相等,则最长前后缀长度加一
- next[i+1] = j+1;
- }
- return next;
- }
有了next数组,我们就可以写出KMP算法了:
- /**
- * KMP搜索字符串
- * @param m 主字符串
- * @param p 模式串
- * @param next next数组
- */
- private static void KMP(String m, String p, int next[]) {
- int j = 0; // 模式串索引
- for (int i = 0; i < m.length(); i++) {
- while (j > 0 && m.charAt(i) != p.charAt(j)) // 字符不相等,模式串右移,由于字符串已有next[i]个相同的前后缀,因此比较索引为next[i]的字符串即可
- j = next[j];
- if (m.charAt(i) == p.charAt(j)) // 字符相等,索引加一
- j++;
- if (j == p.length()) { // 已找到结果
- System.out.println("find the string in " + (i - j + 1));
- break;
- }
- }
- }
最后附上检测用的例子:
- public static void main(String[] args) throws Exception {
- String m = "bacbabababacaab";
- String p = "ababaca";
- int next[] = KMPNext(p);
- KMP(m, p, next);
- }
结果如下:
KMP算法小结的更多相关文章
- KMP算法(转载)
转载http://blog.csdn.net/yutianzuijin/article/details/11954939 kmp算法又称“看毛片”算法,是一个效率非常高的字符串匹配算法.不过由于其难以 ...
- KMP算法学习(详解)
kmp算法又称“看毛片”算法,是一个效率非常高的字符串匹配算法.不过由于其难以理解,所以在很长的一段时间内一直没有搞懂.虽然网上有很多资料,但是鲜见好的博客能简单明了地将其讲清楚.在此,综合网上比较好 ...
- 时序分析:KMP算法用于序列识别
考研基础资料之一的<算法与数据结构>,KMP算法作为串匹配的基本算法,为必考题目之一.对于算法入门来说,也是复杂度稍高的一个基本算法. KMP算法作为串匹配的非暴力算法,是为了减少回溯而设 ...
- 第4章学习小结_串(BF&KMP算法)、数组(三元组)
这一章学习之后,我想对串这个部分写一下我的总结体会. 串也有顺序和链式两种存储结构,但大多采用顺序存储结构比较方便.字符串定义可以用字符数组比如:char c[10];也可以用C++中定义一个字符串s ...
- KMP算法学习以及小结(好马不吃回头草系列)
首先请允许我对KMP算法的三位创始人Knuth,Morris,Pratt致敬,这三位优秀的算法科学家发明的这种匹配模式可以大大避免重复遍历的情况,从而使得字符串的匹配的速度更快,效率更高. 首先引入对 ...
- 浅析KMP算法
浅析KMP算法 KMP算法是一种线性字符串的匹配算法,将主串S与模式串T匹配. 首先朴素算法大家都会,就是直接从S的每一个位置开始,枚举比较,时间效率为O(nm),现在要想到一种化简的方式,使得时间复 ...
- KMP算法中next函数的理解
首先要感谢http://blog.csdn.net/v_july_v/article/details/7041827以及http://blog.chinaunix.net/uid-27164517-i ...
- 单模式串匹配----浅谈kmp算法
模式串匹配,顾名思义,就是看一个串是否在另一个串中出现,出现了几次,在哪个位置出现: p.s. 模式串是前者,并且,我们称后一个 (也就是被匹配的串)为文本串: 在这篇博客的代码里,s1均为文本串, ...
- 字符串模式匹配算法系列(二):KMP算法
算法背景: KMP算法是由Donald Knuth和Vaughan Pratt于1970年共同提出的,而James H.Morris也几乎同时间独立提出了这个算法.因此人们将其称作“克努特-莫里斯-普 ...
随机推荐
- HTTP协议扫盲(七)请求报文之 GET、POST-FORM 和 POST-FILE
一.get 1.页面代码 2.请求报文 3.小结 get请求没有报文体,所以请求报文没有content-type url上的query参数param11=val11¶m12=val12 ...
- git初试
在gitLab上新建一个项目,creat项目文件之后,进入到项目的路径之后,复制命令git clone ‘git@gitlab.touzila.com:xiacaixiang/gitgitTest1. ...
- CWMP开源代码研究番外篇——博通方案
声明:本篇文章来自于某公司Cable Modem产品的文档资料,源码来自于博通公司,只提供参考(为保护产权,本人没有源码). 前文曾提到会写一篇关于博通的tr069,那么福利来了.福利,福利,福利,重 ...
- Python系列 - 进程和线程
进程和线程 可以通过ucos-Ⅱ来学习相关的基础,很好的学习资料 进程 假如有两个程序A和B,程序A在执行到一半的过程中,需要读取大量的数据输入(I/O操作), 而此时CPU只能静静地等待任务A读取完 ...
- sumo快速运行简单仿真实例详细教程
本文旨在让大家快速的了解sumo,并给出运行一个简单的sumo的例子的教程,进而了解基本sumo工程的架构,使大家对该软件产生兴趣并持续学习下去,刚开始学习仿真的确枯燥,项目"跑起来&quo ...
- [LeetCode] Can Place Flowers 可以放置花
Suppose you have a long flowerbed in which some of the plots are planted and some are not. However, ...
- [LeetCode] Remove Boxes 移除盒子
Given several boxes with different colors represented by different positive numbers. You may experie ...
- es6-promise源代码重点难点分析
摘要 vue和axios都可以使用es6-promise来实现f1().then(f2).then(f3)这样的连写形式,es6-promise其实现代浏览器已经支持,无需加载外部文件.由于promi ...
- Mysql中的常用函数:
Mysql中的常用函数: 1.字符串函数: (1).合并字符串 concat():// concat('M','y',"SQL",'5.5');== MySQL5.5//当传入的参 ...
- ●UVA 11021 tunnello
题链: https://vjudge.net/problem/UVA-11021题解: 概率DP. 定义dp[i]表示初始1只麻球的情况下,第i天都死完的概率. (因为每只麻球互相独立,那么最后答案为 ...