KMP算法 --- 深入理解next数组
在KMP算法中有个数组,叫做前缀数组,也有的叫next数组。
每一个子串有一个固定的next数组,它记录着字符串匹配过程中失配情况下可以向前多跳几个字符。
当然它描述的也是子串的对称程度,程度越高,值越大,当然之前可能出现再匹配的机会就更大。
这个next数组的求法是KMP算法的关键,但不是很好理解。这个篇文章仅贡献给不喜欢看数学公式又想理解KMP算法的同学。
1、用一个例子来解释,下面是一个子串的next数组的值,可以看到这个子串的对称程度很高,所以next值都比较大。
位置i |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
前缀next[i] |
0 |
0 |
0 |
0 |
1 |
2 |
3 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
4 |
0 |
子串 |
a |
g |
c |
t |
a |
g |
c |
a |
g |
c |
t |
a |
g |
c |
t |
g |
申明一下:下面说的对称不是中心对称,而是中心字符块对称,比如不是abccba,而是abcabc这种对称。
(1)逐个查找对称串
这个很简单,我们只要循环遍历这个子串,分别看前1个字符,前2个字符,3个... i个 最后到15个。
第1个a无对称,所以对称程度0
前两个ag无对称,所以也是0
依次类推前面0-4都一样是0
前5个agcta,可以看到这个串有一个a相等,所以对称程度为1前6个agctag,看得到ag和ag对成,对称程度为2
这里要注意了,想是这样想,编程怎么实现呢?
只要按照下面的规则:
a、当前面字符的前一个字符的对称程度为0的时候,只要将当前字符与子串第一个字符进行比较。这个很好理解,前面都是0,说明都不对称了,如果多加了一个字符,要对称的话最多是当前的和第一个对称。比如agcta这个里面t的是0,那么后面的a的对称程度只需要看它是不是等于第一个字符a了。
b、按照这个推理,我们就可以总结一个规律,不仅前面是0,如果前面一个字符的next值是1,那么我们就把当前字符与子串第二个字符进行比较,因为前面的是1,说明前面的字符已经和第一个相等了,如果这个又与第二个相等了,说明对称程度就是2了。有两个字符对称了。比如上面agctag,倒数第二个a的next是1,说明它和第一个a对称了,接着我们就把最后一个g与第二个g比较,又相等,自然对称成都就累加了,就是2了。
c、按照上面的推理,如果一直相等,就一直累加,可以一直推啊,推到这里应该一点难度都没有吧,如果你觉得有难度说明我写的太失败了。
当然不可能会那么顺利让我们一直对称下去,如果遇到下一个不相等了,那么说明不能继承前面的对称性了,这种情况只能说明没有那么多对称了,但是不能说明一点对称性都没有,所以遇到这种情况就要重新来考虑,这个也是难点所在。
(2)回头来找对称性
这里已经不能继承前面了,但是还是找对称成都嘛,最愚蠢的做法大不了写一个子函数,查找这个字符串的最大对称程度,怎么写方法很多吧,比如查找出所有的当前字符串,然后向前走,看是否一直相等,最后走到子串开头,当然这个是最蠢的,我们一般看到的KMP都是优化过的,因为这个串是有规律的。
在这里依然用上面表中一段来举个例子:
位置i=0到14如下,我加的括号只是用来说明问题:
(a g c t a g c )( a g c t a g c) t
我们可以看到这段,最后这个t之前的对称程度分别是:1,2,3,4,5,6,7,倒数第二个c往前看有7个字符对称,所以对称为7。但是到最后这个t就没有继承前面的对称程度next值,所以这个t的对称性就要重新来求。
这里首要要申明几个事实
1、t 如果要存在对称性,那么对称程度肯定比前面这个c 的对称程度小,所以要找个更小的对称,这个不用解释了吧,如果大那么t就继承前面的对称性了。
2、要找更小的对称,必然在对称内部还存在子对称,而且这个t必须紧接着在子对称之后。
如下图说明。
从上面的理论我们就能得到下面的前缀next数组的求解算法。
{
Next[0]=0;
int len=strlen(s);
for(int i=1; i<len; i++)
{
int k=Next[i-1];
//不断递归判断是否存在子对称,k=0说明不再有子对称,s[i] != s[k]说明虽然对称,但是对称后面的值和当前的字符值不相等,所以继续递推
while( s[i] != s[k] && k!=0 )
k=Next[k-1]; //继续递归
if( s[i] == s[k])//找到了这个子对称,或者是直接继承了前面的对称性,这两种都在前面的基础上++
Next[i]=k+1;
else
Next[i]=0; //如果遍历了所有子对称都无效,说明这个新字符不具有对称性,清0
}
}
通过这个说明,估计能够理解KMP的next求法原理了。
KMP算法 --- 深入理解next数组相关推荐
- 转载大神的~~~~~~ KMP算法的前缀next数组最通俗的解释,如果看不懂我也没辙了
KMP算法的前缀next数组最通俗的解释,如果看不懂我也没辙了 分类: 常用基础算法 IT经典笔试题 2012-09-02 10:09 1042人阅读 评论(1) 收藏 举报 算法 c 编程 ...
- 深化对KMP算法的理解
KMP算法 看到这么一句话:你的名字是我告白语中的子串 文章目录 KMP算法 参考代码 预处理模式串的理解 入门题目 KMP一开始理解起来是比较困难的,下方是结合自己的理解写出来代码,仅作参考, (网 ...
- No.5终于搞懂了kmp算法(精髓为next数组的求解过程,此文next数组未经过优化)
背景 KMP 是经典的字符串匹配算法,在大学课本里面都是讲到过的,不过我感觉课本都讲的太生硬了,很容易忘记.大多数博客也是讲的云里雾里的,一开始就来个公式+部分匹配表,反正我感觉对于没有计算机基础的童 ...
- 字符串匹配KMP算法的理解(详细)
1. 引言 本KMP原文最初写于2年多前的2011年12月,因当时初次接触KMP,思路混乱导致写也写得混乱.所以一直想找机会重新写下KMP,但苦于一直以来对KMP的理解始终不够,故才迟迟没有修改本文. ...
- 匹配字符串之——KMP算法深入理解
KMP算法的用途 一般在字符串匹配的时候,我们通常想到的就是使用KMP算法来处理. KMP的使用,在网上有很多实例,但是讲得很让人容易接受的不是很多,但总感觉那层窗户纸没有捅破,这里我结合前人的知识, ...
- KMP算法的前缀next数组最通俗的解释,如果看不懂我也没辙了
我们在一个母字符串中查找一个子字符串有很多方法.KMP是一种最常见的改进算法,它可以在匹配过程中失配的情况下,有效地多往后面跳几个字符,加快匹配速度. 当然我们可以看到这个算法针对的是子串有对称属性, ...
- KMP算法讲解(next数组求解)
KMP算法 关于算法部分,网上有比较多写的好的博客了,下面是我看到的一篇.https://blog.csdn.net/liu88010988/article/details/50789960 这种算法 ...
- KMP算法的理解,伪代码,c代码实现
2019独角兽企业重金招聘Python工程师标准>>> 1.字符串问题形式化定义:假设文本是一个长度为n的T[1..n],而模式是一个长度为m的数组P[1..m],其中m<=n ...
- KMP算法中的next数组求解
KMP算法是在模式串的next数组基础上进行的,如何求解next数组就成了关键. next数组的求解和主串无关,只与模式串自身相关. 则next[j]= -1, 当j=0时 Max {k|0<k ...
最新文章
- show-busy-java-threads查找CPU占用高
- abaqus分析用户手册单元卷_作用卷、分析卷、材料卷三件套,让你也能熟练应用Abaqus...
- ios一个app调起另一个app_电商app开发价格:制作一个电商app需要多少钱?
- windows 7关闭休眠
- 「知识表示学习」专题论文推荐 | 每周论文清单
- 使用.net core3.0 正式版创建Winform程序
- 机器学习速成课程 | 练习 | Google Development——编程练习:稀疏性和 L1 正则化
- delphi解析json(解决乱码问题)
- 简易JTAG线缆原理
- Linux: kill
- 顶顶顶!!	Xcode7.1下用CocoaPods安装Alamofire--swift下的第三方网络库
- android桌面工具,不一样的Android桌面小工具
- 西南科技大学城市学院计算机专业录取分数线,西南科技大学城市学院2020年录取分数线(附2017-2020年分数线)...
- html快捷方式指定浏览器打开网页,设置桌面网址快捷方式,并默认使用指定浏览器打开...
- 清华2018计算机研究所录取结果,2018年清华北大自主招生录取名单公布!
- Nginx正反向代理的具体步骤讲解
- 贝壳找房户外拓展(中等) 扫描线
- simulink中的s-function的直接馈入
- unity上传头像_unity3d 上传本地PC图片
- IDEA配置及常用设置
热门文章
- mfc-PlaySound
- 软考信息系统项目管理师_信息系统综合测试与管理---软考高级之信息系统项目管理师027
- python_程序格式_缩进_行注释_段注释---python工作笔记012
- AndroidStudio_android通过自定义来实现倒计时的AlertDialog---Android原生开发工作笔记245
- 使用tensorwatchimport pdb import tensorwatch as tw import torchvision.models alexnet_model = torchv可视化
- 发现Diolar 的边缘检测程序好像也有缺点
- Symbol'' has different size in shared object,consider re-linking
- 杭电2531Catch him
- 3d激光雷达开发(法向量预测)
- 随想录(内核模块的测试方法)