【转载】KMP入门级别算法详解--终于解决了(next数组详解)
【转载】https://blog.csdn.net/LEE18254290736/article/details/77278769
对于正常的字符串模式匹配,主串长度为m,子串为n,时间复杂度会到达O(m*n),而如果用KMP算法,复杂度将会减少线型时间O(m+n)。
设主串为ptr="ababaaababaa";,要比较的子串为a=“aab”;
KMP算法用到了next数组,然后利用next数组的值来提高匹配速度,我首先讲一下next数组怎么求,之后再讲匹配方式。
next数组详解
首先是理解KMP算法的第一个难关是next数组每个值的确定,这个问题困恼我很长时间,尤其是对照着代码一行一行分析,很容易把自己绕进去。
定义一串字符串
ptr = "ababaaababaa";
next[i](i从1开始算)代表着,除去第i个数,在一个字符串里面从第一个数到第(i-1)字符串前缀与后缀最长重复的个数。
什么是前缀?
在“aba”中,前缀就是“ab”,除去最后一个字符的剩余字符串。
同理可以理解后缀。除去第一个字符的后面全部的字符串。
在“aba”中,前缀是“ab”,后缀是“ba”,那么两者最长的子串就是“a”;
在“ababa”中,前缀是“abab”,后缀是“baba”,二者最长重复子串是“aba”;
在“abcabcdabc”中,前缀是“abcabcdab”,后缀是“bcabcdabc”,二者最长重复的子串是“abc”;
这里有一点要注意,前缀必须要从头开始算,后缀要从最后一个数开始算,中间截一段相同字符串是不行的。
再回到next[i]的定义,对于字符串ptr = "ababaaababaa";
next[1] = -1,代表着除了第一个元素,之前前缀后缀最长的重复子串,这里是空 ,即"",没有,我们记为-1,代表空。(0代表1位相同,1代表两位相同,依次累加)。
next[2] = -1,即“a”,没有前缀与后缀,故最长重复的子串是空,值为-1;
next[3] = -1,即“ab”,前缀是“a”,后缀是“b”,最长重复的子串“”;
next[4] = 1,即"aba",前缀是“ab”,后缀是“ba”,最长重复的子串“a”;next数组里面就是最长重复子串字符串的个数
next[5] = 2,即"abab",前缀是“aba”,后缀是“bab”,最长重复的子串“ab”;
next[6] = 3,即"ababa",前缀是“abab”,后缀是“baba”,最长重复的子串“aba”;
next[7] = 1,即"ababaa",前缀是“ababa”,后缀是“babaa”,最长重复的子串“a”;
next[8] = 1,即"ababaaa",前缀是“ababaa”,后缀是“babaaa”,最长重复的子串“a”;
next[9] = 2,即"ababaaab",前缀是“ababaaa”,后缀是“babaaab”,最长重复的子串“ab”;
next[10] = 3,即"ababaaaba",前缀是“ababaaab”,后缀是“babaaaba”,最长重复的子串“aba”;
next[11] = 4,即"ababaaabab",前缀是“ababaaaba”,后缀是“babaaabab”,最长重复的子串“abab”;
next[12] = 5,即"ababaaababa",前缀是“ababaaabab”,后缀是“babaaaababa”,最长重复的子串“ababa”;
还有另外一种方法,我看的有的书上写着:
这里我们定义next[1] = 0 , next[1] = 1;
再分析ptr字符串,ptr = "ababaaababaa";
跟上一个的情况类似,
next[1] = 0 ,事先定义好的
next[2] = 1 ,事先定义好的
next[3] = 1 ,最长重复的子串“”;1代表没有重复,2代表有一个字符重复。
next[4] = 2 ,最长重复的子串“a”;追偿的长度加1,即为2.
next[5] = 3 ,以下都跟之前的一样,这种方法是最长的长度再加上一就可以了。
next[6] = 4
next[7] = 2
next[8] = 2
next[9] = 3
next[10] = 4
next[11] = 5
next[12] = 6
以上是next数组的详细解释。next数组求值 是比较麻烦的,剩下的匹配方式就很简单了。
next数组用于子串身上,根据上面的原理,我们能够推出子串a=“aab”的next数组的值分别为0,1,2.(按照我说的第二种方式算的)。
首先开始计算主串与子串的字符,设置主串用i来表示,子串用j来表示,如果ptr[i]与a[i]相等,那么i与j就都加1:
prt[1]与a[1]相等,i++,j++:
用代码实现就是
- if( j==0 || ptr[i]==a[j])
- {
- ++i;
- ++j;
- }
ptr[2]与a[2]不相等
此时ptr[2]!=a[2],那么令j = next[j],此时j=2,那么next[j] = next[2] = 1.那么此时j就等于1.这一段判断用代码解释的话就是:
- if( ptr[i]!=a[j])
- {
- j = next[j];
- }
加上上面的代码进行组合:
在对两个数组进行比对时,各自的i,j取值代码:
- <span style="font-size:18px;">while( i<ptr.length && j< a.length)
- {
- if( j==0 || ptr[i]==a[i] )
- {
- ++i;
- ++j;</span>
- <span style="font-size:18px;"> next[i] = j;
- }
- else
- {
- j = next[j];
- }
- }</span>
此时将a[j]置于j此时所处的位置,即a[1]放到j=2处,因为在j=2时出现不匹配的情况。
此时再次计算是否匹配,可以看出来a[1]!=ptr[2],那么j = next[j],即此时j = next[1] = 0;
根据上面的代码,当j=0时,执行++i;++j;
此时就变为:
此时ptr[3] = a[1],继续向下走,下一个又不相等了,然后“aab”向后挪一位,这里不再赘述了,主要的思想已经讲明白了。到最后一直到i = 8,j=3时匹配成功,KMP算法结束。整个过程就结束了。
【转载】KMP入门级别算法详解--终于解决了(next数组详解)的更多相关文章
- ES6_入门(4)_数组的解构赋值
//2017/7/14 //变量的解构赋值(解构:Destructuring) //(1)数组的解构赋值 let [a,b,c]=[1,2,3];//模式匹配,只要等号两边的模式相同,左边的变量就会被 ...
- 花了5天时间,终于解决了一个bug,心情非常愉快,憋了这么久,不吐不快
http://www.cnweblog.com/fly2700/archive/2011/12/06/318916.html (转载) 花了5天时间,终于解决了一个bug,心情非常愉快,憋了这么久,不 ...
- 转载 CSS3 经典教程系列:CSS3 盒阴影(box-shadow)详解
目标大纲 文章转载 CSS3 经典教程系列:CSS3 盒阴影(box-shadow)详解 IE中CSS-filter滤镜小知识大全 CSS实现跨浏览器兼容性的盒阴影效果
- 转载 - KMP算法
出处:http://www.cnblogs.com/dolphin0520/archive/2011/08/24/2151846.html KMP算法 在介绍KMP算法之前,先介绍一下BF算法. 一. ...
- 【原创】视频+文字:详解VBA解决数独问题
[说在前面]: 之前,我在微信朋友圈看到一个同事发了一个状态,说的是她在家辅导孩子做作业,一个数独的题目,好像没有做出来.我看了下,我也做不出来,后来仔细想了下,花了两个多小时时间,用Python编了 ...
- spring事务详解(三)源码详解
系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...
- 大话数据结构(8) 串的模式匹配算法(朴素、KMP、改进算法)
--喜欢记得关注我哟[shoshana]-- 目录 1.朴素的模式匹配算法2.KMP模式匹配算法 2.1 KMP模式匹配算法的主体思路 2.2 next[]的定义与求解 2.3 KMP完整代码 2.4 ...
- [转载]花了半个月,终于把Python库全部整理出来了,非常全面
库名称简介 Chardet 字符编码探测器,可以自动检测文本.网页.xml的编码. colorama 主要用来给文本添加各种颜色,并且非常简单易用. Prettytable 主要用于在终端或浏览器端构 ...
- 服务器TIME_WAIT和CLOSE_WAIT详解和解决办法
转载的服务器TIME_WAIT和CLOSE_WAIT详解和解决办法
随机推荐
- Second My Problem First HDU - 3706 单调队列
单调队列 单调队列是指一个队列内部的元素具有严格单调性的一种数据结构,分为单调递增队列和单调递减队列. 单调队列满足两个性质 1.单调队列必须满足从队头到队尾的严格单调性. 2.排在队列前面的比排在队 ...
- URAL - 1635 哈希区间(或者不哈希)+dp
题意: 演队在口试中非常不幸.在42道考题中,他恰好没有准备最后一道题,而刚好被问到的正是那道题.演队坐在教授面前,一句话也说不出来.但教授心情很好,给了演队最后一次通过考试的机会.他让这个可怜的学生 ...
- 注意力(Attention)与Seq2Seq的区别
什么是注意力(Attention)? 注意力机制可看作模糊记忆的一种形式.记忆由模型的隐藏状态组成,模型选择从记忆中检索内容.深入了解注意力之前,先简要回顾Seq2Seq模型.传统的机器翻译主要基于S ...
- codeforces 1036B - Diagonal Walking v.2【思维+构造】
题目:戳这里 题意:起点(0,0),终点(n,m),走k步,可以走8个方向,问能不能走到,能走到的话最多能走多少个斜步. 解题思路:起点是固定的,我们主要分析终点.题目要求走最多的斜步,斜步很明显有一 ...
- 为树莓派3B添加LCD1602液晶屏
树莓派3B针脚说明 LCD1602接线说明 VSS,接地VDD,接5V电源VO,液晶对比度调节,接电位器中间的引脚,电位器两边的引脚分别接5V和接地.RS,寄存器选择,接GPIO14RW,读写选择,接 ...
- SpringBoot 全局视角看springboot
从单体架构到微服务 单体架构 任何一个网站在发布初期几乎都不可能立马就拥有庞大的用户流量和海量数据,都是在不停 的试错过程中一步一步演变其自身架构,满足其自身业务.比如现在能够抗住双十一这么大 流量的 ...
- js screen size check
js screen size check js 屏幕尺寸检测 window.screen API screen; window.screen.width; window.screen.height; ...
- js coverage testing
js coverage testing 测试覆盖率 istanbul 伊斯坦堡/伊斯坦布尔 https://istanbul.js.org/ jest coverage https://jestjs. ...
- 如何正确的使用 Dart SDK API
如何正确的使用 Dart SDK API dart-core dart:core library https://api.dart.dev/stable/2.9.1/dart-core/dart-co ...
- css dark theme & js theme checker
css dark theme & js theme checker live demo https://codepen.io/xgqfrms/pen/GRprYLm <!DOCTYPE ...