来去学习之---KMP算法--next计算过程
一、概述
KMP算法是一种字符串匹配算法,比如现有字符串
T:ABCDABCDABCDCABCDABCDE,
P:ABCDABCDE
P字符串对应的next值:[0,0,0,0,1,2,3,4,0]
二、匹配过程
判断T字符串是否包含P字符串?下面看一下KMP的比较过程:
三、next数组计算过程
先了解一下字符串的前后缀(具体来说是真前后缀即 前缀不包含最后一个字符;后缀不包含第一个字符)
字符串 |
真前缀 |
真后缀 |
真前、后缀中相 同的字符串 |
真前、后缀中 最大相同串 |
真前、后缀中最 大相同串字符数 |
abc |
a,ab |
bc,c |
无 |
无 |
0 |
aaa |
a,aa |
aa,a |
a,aa |
aa |
2 |
aba |
a,ab |
ba,a |
a |
a |
1 |
abab |
a,ab,aba |
bab,ab,b |
ab |
ab |
2 |
ababab |
a,ab,aba,abab,ababa |
babab,abab,bab,ab,b |
ab,abab |
abab |
4 |
那“ABCDABCDE”字符串的最大真前后缀的计算过程如下:
子串 |
真前缀字符串 |
真后缀字符串 |
真前、后缀中最 大相同串字符 |
真前、后缀中最 大相同串字符数 |
A |
无 |
无 |
无 |
0 |
AB |
A |
B |
无 |
0 |
ABC |
AB、A |
BC、C |
无 |
0 |
ABCD |
ABC、AB、A |
BCD、CD、D |
无 |
0 |
ABCDA |
ABCD、ABC、AB、A |
BCDA、CDA、DA、A |
A=A |
1 |
ABCDAB |
ABCDA、ABCD、ABC、AB、A |
BCDAB、CDAB、DAB、AB、B |
AB=AB |
2 |
ABCDABC |
ABCDAB、ABCDA、ABCD、 ABC、AB、A |
BCDABC、CDABC、DABC、 ABC、BC、C |
ABC=ABC |
3 |
ABCDABCD |
ABCDABC、ABCDAB、ABCDA、 ABCD、ABC、AB、A |
BCDABCD、CDABCD、DABCD、 ABCD、BCD、CD、D |
ABCD=ABCD |
4 |
ABCDABCDE |
ABCDABCD、ABCDABC、ABCDAB、 ABCDA、ABCD、ABC、AB、A |
BCDABCDE、CDABCDE、DABCDE、 ABCDE、BCDE、CDE、DE、E |
无 |
0 |
由上表得出最大真前后缀的结果为:{0,0,0,0,1,2,3,4,0}
接下来需要把这最大真前后缀值转换为next值
索引 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
字符串 |
A |
B |
C |
D |
A |
B |
C |
D |
E |
最大真前后缀数 |
0 |
0 |
0 |
0 |
1 |
2 |
3 |
4 |
0 |
Next |
-1 |
0 |
0 |
0 |
0 |
1 |
2 |
3 |
4 |
通过上面的表格可以发现就是把最大真前后缀的值整体向后以后一位,所以next值为:{-1,0,0,0,0,1,2,3,4},计算出这个next数组之后,接下来在匹配的过程中就可以使用了。
注意:有的人感觉使用最大真前后缀也可以作为next值,这是可以作为的,只是在计算最大真前后缀的逻辑代码相对复杂一点点,并且在匹配使用的时候也会复杂一点点
四、实现代码
计算next值的代码
1 public static int[] computeNext(char[] chs) {
2 int i = 0;
3 int j = -1;
4 int[] next = new int[chs.length];
5 next[i] = j;
6 while (i < chs.length - 1) {
7 if (j == -1 || chs[i] == chs[j]) {
8 i++;
9 j++;
10 next[i] = j;
11 } else {
12 j = next[j];
13 }
14 }
15 return next;
16 }
计算最大真前后缀的代码:
1 public static int[] getPreSuffix(char[] cs) {
2 int j = 0;
3 int i = 1;
4 int len = cs.length;
5 int[] preSuffix = new int[len];
6 preSuffix[1] = 0;
7 while (i < len) {
8 if (j == 0) {
9 if (cs[j] == cs[i]) {
10 preSuffix[i] = j + 1;
11 j++;
12 i++;
13 } else {
14 i++;
15 }
16 } else {
17 if (cs[j] == cs[i]) {
18 preSuffix[i] = j + 1;
19 j++;
20 i++;
21 } else {
22 j = preSuffix[j - 1];
23 }
24 }
25 }
26 return preSuffix;
27 }
大家有什么疑问、建议欢迎留言、讨论!
来去学习之---KMP算法--next计算过程的更多相关文章
- 学习笔记-KMP算法
按照学习计划和TimeMachine学长的推荐,学习了一下KMP算法. 昨晚晚自习下课前粗略的看了看,发现根本理解不了高端的next数组啊有木有,不过好在在今天系统的学习了之后感觉是有很大提升的了,起 ...
- [一本通学习笔记] KMP算法
KMP算法 对于串s[1..n],我们定义fail[i]表示以串s[1..i]的最长公共真前后缀. 我们首先考虑对于模式串p,如何计算出它的fail数组.定义fail[0]=-1. 根据“真前后缀”的 ...
- KMP算法之查找模式串在源串中出现的次数
问题描述: 给定两个字符串T, P.查找字符串P在字符串T中出现的次数. 解决方法: 典型的KMP算法的题目,在此使用的KMP算法为算法导论上介绍的算法.下一篇文章将详细介绍KMP算法的计算过程. 题 ...
- 关于《数据结构》课本KMP算法的理解
数据结构课上讲的KMP算法和我在ACM中学习的KMP算法是有区别的,这里我对课本上的KMP算法给出我的一些想法. 原理和之前的KMP是一样的https://www.cnblogs.com/wkfvaw ...
- KMP算法 Next数组详解
题面 题目描述 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.如果你不知道这是什么意思也不要问,去百 ...
- 字符串匹配的 KMP算法
一般字符串匹配过程 KMP算法是字符串匹配算法的一种改进版,一般的字符串匹配算法是:从主串(目标字符串)和模式串(待匹配字符串)的第一个字符开始比较,如果相等则继续匹配下一个字符, 如果不相等则从主串 ...
- 数据结构4_java---顺序串,字符串匹配算法(BF算法,KMP算法)
1.顺序串 实现的操作有: 构造串 判断空串 返回串的长度 返回位序号为i的字符 将串的长度扩充为newCapacity 返回从begin到end-1的子串 在第i个字符之前插入字串str 删除子串 ...
- 程序员的算法课(11)-KMP算法
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/m0_37609579/article/de ...
- KMP算法,看这篇就够了!
普通的模式匹配算法(BF算法) 子串的定位操作通常称为模式匹配算法 假设有一个需求,需要我们从串"a b a b c a b c a c b a b"中,寻找内容为"a ...
随机推荐
- [bzoj5507] [洛谷P5305] [gzoi2019]旧词
Descriptioin 浮生有梦三千场 穷尽千里诗酒荒 徒把理想倾倒 不如早还乡 温一壶风尘的酒 独饮往事迢迢 举杯轻思量 泪如潮青丝留他方 --乌糟兽/愚青<旧词> 你已经解决了五个问 ...
- 4、python基础语法
前言:本文主要介绍python的一些基础语法,包括标识符的定义.行和缩进.引号和注释.输入输出.变量的定义. 一.标识符 1.凡是我们自己取的名字,都是标识符. 2.在Python里,标识符由字母.下 ...
- Python-直接存储类实例作为序列的元素
如果我们需要存储的数据有很多属性,并且存储的数量很多,可选择定义一个类来表示数据类型,而类的实体作为单个的成员进行存储,这样做的好处是可以只存储一个容器,而不需要每次都存储大量的数据,并且可以限制对数 ...
- ip 地址库 这个 准么 呢
- kuangbin专题专题十一 网络流 POJ 1087 A Plug for UNIX
题目链接:https://vjudge.net/problem/POJ-1087 题目:有n个插座,插座上只有一个插孔,有m个用电器,每个用电器都有插头,它们的插头可以一样, 有k个插孔转化器, a ...
- Windows中安装Linux子系统的详细步骤
早就听说Windows中可以安装Linux子系统,体验了一下,感觉还是不错的,下面直接开始安装和配置步骤吧! 开启Windows中的配置 首先开启开发者模式 打开"所有设置"进入& ...
- .Net Core建站(1):EF Core+CodeFirst数据库生成
emmm,本来想着用Core做一个小项目玩玩的,然后肯定是要用到数据库的, 然后想,啊,要不用CodeFirst,感觉很腻害的样子,于是,一脸天真无邪的我就踏入了一个深不见底的天坑... 本来想着,应 ...
- http轮询,长轮询
轮询,长轮询 轮询 轮询:客户端定时向服务器发送Ajax请求,服务器接到请求后马上返回响应信息并关闭连接. 优点:后端程序编写比较容易. 缺点:请求中有大半是无用,浪费带宽和服务器资源. 实例:适于小 ...
- Spring注解开发系列Ⅸ --- 异步请求
一. Servlet中的异步请求 在Servlet 3.0之前,Servlet采用Thread-Per-Request的方式处理请求,即每一次Http请求都由某一个线程从头到尾负责处理.如果要处理一些 ...
- Docker的save和export命令的区别
我最近在玩Docker,一种应用程序容器和Linux的虚拟技术.它太酷了,创建Docker镜像和容器只需要几分钟.所有的工作都是开箱即用的. 在结束我一天的工作之前,我希望能保存下我的工作.但我在Do ...