KMP算法中的next函数
原文链接:http://blog.csdn.net/joylnwang/article/details/6778316/
其实后面大段的代码都可以不看
KMP的关键是next的产生
这里使用了中间变量f
下面是原文
"""
这里我们引入一个概念f(j),其含义是,对于模式串的第j个字符pattern[j],f(j)是所有满足使pattern[1...k-1] = pattern[j-(k-1)...j - 1](k < j)成立的k的最大值。还是以模式串abcabcacab为例,当处理到pattern[8] = 'c'时,我们想找到'c'前面的k-1个字符,使得pattern[1...k-1] = pattern[8-(k-1)...7],这里我们可以使用一个笨法,让k-1从1到6递增,然后依次比较,直到找到最大值的k为止,比较过程如下
| k-1 | 前缀 | 关系 | 子串 |
| 1 | a | == | a |
| 2 | ab | != | ca |
| 3 | abc | != | bca |
| 4 | abca | == | abca |
| 5 | abcab | != | cabca |
| 6 | abcabc | != | bcabca |
因为要取最大的k,所以k-1=1不是我们要找的结果,最后求出k的最大值为4+1=5。但是这样的方法比较低效,而且没有充分利用到之前的计算结果。在我们处理pattern[8] = 'c'之前,pattern[7] = 'a'的最大前缀包含问题已经解决,f(7) = 4,也就是说,pattern[4...6] = pattern[1...3],此时我们可以比较pattern[7]与pattern[4],如果pattern[4]=pattern[7],对于pattern[8]而言,说明pattern[1...4]=pattern[4...7],此时,f(8) = f(7) + 1 = 5。再以pattern[9]为例,f(8) = 5,pattern[1...4]=pattern[4...7],但是pattern[8] != pattern[5],所以pattern[1...5]!=pattern[4...8],此时无法利用f(8)的值直接计算出f(9)。
"""
如此 通过f(n-1)推导f(n)已经成功了一半
我们已经知道了当pattern(n-1)==pattern(f(n-1))的情况下f(n)=f(n-1)+1
那么左边!=右边的情况下呢?
原文中先介绍了next的求法
next很好求 当pattern(n) != pattern(f(n))时 next(n)=f(n)
当左边等于右边时考虑pattern(n)是否等于pattern(f(f(n))) 如此一直递归直到不等即可 看起来很多括号可能有点晕,但是仔细思考一下next函数的意义就能很轻松的得到它与f函数的关系了
那么继续上面的内容 通过f(n-1)推导f(n) 的剩下一半该怎么解决
当左边!=右边时,我们求出通过刚才了解到的方法求出next(n-1)
以下是原文
"""
当要求f(9)时,f(8)和next[8]已经可以得到,此时我们可以考察pattern[next[8]],根据前面对于next值的计算方式,我们知道pattern[8] != pattern[next[8]]。我们的目的是要找到pattern[9]的包含前缀,而pattern[8] != pattern[5],pattern[1...5]!=pattern[4...8]。我们继续考察pattern[next[5]]。如果pattern[8] = pattern[next[5]],假设next[5] = 3,说明pattern[1...2] = pattern[6...7],且pattern[3] = pattern[8],此时对于pattern[9]而言,就有pattern[1...3]=pattern[6...8],我们就找到了f(9) = 4。这里我们考察的是pattern[next[j]],而不是pattern[f(j)],这是因为对于next[]而言,pattern[j] != pattern[next[j]],而对于f()而言,pattern[j]与pattern[f(j)]不一定不相等,而我们的目的就是要在pattern[j] != pattern[f(j)]的情况下,解决f(j+1)的问题,所以使用next[j]向前回溯,是正确的。
"""
如果有耐心认真看完上面那一段很绕的话那么其实解决方法已经很明显了
就是通过递归找出pattern(x)==pattern(n-1)其中x=next(next(next(n-1))) (这里next并不是一定是三层 只是打个比方 一直递归下去直到找到第一个pattern值等于pattern(n-1))的为止
KMP算法中的next函数的更多相关文章
- KMP算法中我对获取next数组的理解
之前在学KMP算法时一直理解不了获取next数组的函数是如何实现的,现在大概知道怎么一回事了,记录一下我对获取next数组的理解. KMP算法实现的原理就不再赘述了,先上KMP代码: 1 void g ...
- 问题 1690: 算法4-7:KMP算法中的模式串移动数组
题目链接:https://www.dotcpp.com/oj/problem1690.html 题目描述 字符串的子串定位称为模式匹配,模式匹配可以有多种方法.简单的算法可以使用两重嵌套循环,时间复杂 ...
- KMP 算法中的 next 数组
KMP 算法中对 next 数组的理解 next 数组的意义 此处 next[j] = k:则有 k 前面的浅蓝色区域和 j 前面的浅蓝色区域相同: next[j] 表示当位置 j 的字符串与主串不匹 ...
- KMP算法中next函数的理解
首先要感谢http://blog.csdn.net/v_july_v/article/details/7041827以及http://blog.chinaunix.net/uid-27164517-i ...
- KMP算法中next数组的理解与算法的实现(java语言)
KMP 算法我们有写好的函数帮我们计算 Next 数组的值和 Nextval 数组的值,但是如果是考试,那就只能自己来手算这两个数组了,这里分享一下我的计算方法吧. 计算前缀 Next[i] 的值: ...
- KMP算法中求next数组的实质
在串匹配模式中,KMP算法较蛮力法是高效的算法,我觉得其中最重要的一点就是求next数组: 看了很多资料才弄明白求next数组是怎么求的,我发现我的忘性真的比记性大很多,每次看到KMP算法求next数 ...
- kmp算法中的nextval实例解释
求nextval数组值有两种方法,一种是不依赖next数组值直接用观察法求得,一种方法是根据next数组值进行推理,两种方法均可使用,视更喜欢哪种方法而定. 本文主要分析nextval数组值的第二种方 ...
- 关于KMP算法中,获取next数组算法的理解
参考:KMP入门级别算法详解--终于解决了(next数组详解) https://blog.csdn.net/lee18254290736/article/details/77278769 在这里讨论的 ...
- KMP算法中的几个疑问
KMP算法next数组求解实现 首先我们通过应用场景将KMP算法中用到的名词做一个说明: 在一个字符串(string1)中查询是否存在另一个字符串(string2). 在字符串匹配算法中,我们通常将字 ...
随机推荐
- ELK集群之elasticsearch(3)
Elasticsearch-基础介绍及索引原理分析 介绍 Elasticsearch 是一个分布式可扩展的实时搜索和分析引擎,一个建立在全文搜索引擎 Apache Lucene(TM) 基础上的搜索引 ...
- Qt 实时显示系统时间
前言 我们用一个label控件来实时显示系统时间,用到 QTimer 和 QDateTime 这个两个类. 正题 头文件: #ifndef MAINWINDOW_H #define MAINWINDO ...
- 手把手从0到1:搭建Kubernetes集群
搭建 k8s 集群网上很多教程,如果是手工部署或者实验环境可以直接使用 MiniKube 或者 Kind,来在本地启动简单的 Kubernetes 集群进行后面的学习即可.如果是使用 MiniKube ...
- rz安装
rpm -ivh http://www.rpmfind.net/linux/centos/6.10/os/x86_64/Packages/lrzsz-0.12.20-27.1.el6.x86_64.r ...
- python unicode escape
from: https://stackoverflow.com/questions/44742806/how-to-remove-escape-characters-escaping-unicode- ...
- Typora的基础操作
#一级标题 ##二级标题 ###三级标题 ####四级标题 加粗 倾斜 加粗又倾斜 ---下划线 插入图片 英文状态下 感叹号+中括号+小括号 //中括号内为图片名字 若想插入网络图片 在网络上找一个 ...
- [hdu7078]Pty with card
显然问题被分为两部分,先考虑如何求$F(n)$-- 令第一次所选的人编号为1,其之后所有人按顺时针依次编号为$2,3,...,n$,那么用一个序列来描述状态,其中第$i$个元素为当前存在的人中编号第$ ...
- vue3 + vite实现异步组件和路由懒加载
在 Vue2 中,异步组件和路由懒加载处理使用 import 就可以很轻松实现.但是在Vue 3.x 中异步组件的使用与 Vue 2.x 完全不同了.本文就详细讲讲vue3中异步组件和路由懒加载的实现 ...
- Semaphore信号量的使用
package ThreadTest; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; pub ...
- idea 的git代码回退回某个版本
intellij idea 的git代码回退回滚 找到Reset HEAD 填写提交码,注意这里要选择"hard" 使用命令行强制提交代码 git push -f