我对KMP算法的理解
KMP算法的核心在于失配回溯表——pnext,相比于通过逐个比较来匹配字符串的朴素算法,KMP通过对模式串的分析,可以做到比较指针在主串上不回溯,一直向前。
1. KMP如何实现不回溯?
对于主串 t0 t1....tj,模式串 p在 pi处与 tj 失配,假设 p0~pi-1 存在最长相等前后缀,可以证明将模式串移动至该前缀的后一位,再将其与 tj进行比较,不会漏掉可能的匹配,并且可以大大加速匹配过程。并且这种移动与具体主串无关,仅仅与模式串的失配位置 i 有关,可以通过提前分析模式串,得到失配后的串移动表pnext。
2. 如何得到pnext?
pnext表实质上记录的是模式串中前 i 个元素形成的子串,其最长相等前后缀的大小。即pnext [ i ] 记录着p0到pi-1的子串最长相等前后缀的大小。
具体实现方法就是用模式串自身去逐个比对自身,由前后缀的定义可知,头元素没有相等前后缀,pnext [1]=0。用第0个元素去比对第1个元素,当p0=p1时,pnext [2]=1,接下来比较p1是否等p2;否则pnext [2]=0,接下来继续比较p0是否等p2.......
更一般的,当已知模式串中pnext [ i-1]=k-1,即 p0~pk-2与 pi-k~pi-2求pnext [ i ]。分两种情况:
1)当pi-1=pk-1时,对于i-1的最长相等前后缀,比i-2要多1,那么可以得到pnext [ i ]=k,指针后移,开始求pnext [ i+1];
2)当pi-1!=pk-1时,这时我们需要在 p0~pk-1中继续向前找,在 pi-k~pi-1中继续向后找,寻找新的最长相等前后缀。假设我们寻找到了该串,即前缀为 p0~px-1,后缀为 pi-x~pi-1,那么由于pi-1!=pk-1,而pi-1=px-1。表明px-1!=pk-1,这说明串p0~px-2一定是pk-1的最长相等前后缀串,即pnext [ k ]=x-1。因此当pi-1!=pk-1时,可以直接比对pi-1是否等于ppnext[ k ]!!!此时问题变为:已知模式串中pnext [ i-1]=k-1,求pnext [ i ],其中i-1实际为k,k-1实际值为x-1。若比对成功,则pnext [ i ]=x,指针后移,否则直接比对pi-1是否等于ppnext[ pnext[ k ] ]。问题形成了递归。
将这种递归求值关系与边界条件相结合,我们注意到当p1 !=p0时,pnext [2]=0= -1+1,可以设pnext [0]=-1,则整个求pnext表值过程可以用一个函数统一起来。求值过程从1号位值开始。
def my_pnext(p):
'''模式串的pnext表生成函数'''
m=len(p)
pnext=[-1]*m
i,k=0,-1
while i<m-1:
'''当k=-1时,说明pi != p0 ,没有最大相等前后缀,此时pnext[i]应为0
同样可以将i,k都加1,进行赋值'''
if k==-1 or p[i]==p[k]:
i,k=i+1,k+1
pnext[i]=k
else:
k=pnext[k]
return pnext
相应的KMP函数为:
def my_kmp(t,p,pnext):
'''t是主串,p是模式串,pnext是模式串kmp算法的回溯指针表'''
j,i=0,0
n,m=len(t),len(p)
while j<n and i<m:
if i==-1 or t[j]==p[i]:
j,i=j+1,i+1
else:
i=pnext[i]
if i==m:
return j-i
return -1
我对KMP算法的理解的更多相关文章
- 自己对kmp算法的理解,借由 28. 实现 strStr() 为例
做题思路 or 感想 : 就借由这道题来理解一下kmp算法吧 kmp算法的操作过程我觉得有句话很合适 :KMP 算法永不回退 目标字符串 的指针 i,不走回头路(不会重复扫描 目标字符串),而是借助 ...
- KMP算法 --- 深入理解next数组
在KMP算法中有个数组,叫做前缀数组,也有的叫next数组. 每一个子串有一个固定的next数组,它记录着字符串匹配过程中失配情况下可以向前多跳几个字符. 当然它描述的也是子串的对称程度,程度越高,值 ...
- KMP算法的理解
---恢复内容开始--- 在看数据结构的串的讲解的时候,讲到了KMP算法——一个经典的字符串匹配的算法,具体背景自行百度之,是一个很牛的图灵奖得主和他的学生提出的. 一开始看算法的时候很困惑,但是算法 ...
- 关于《数据结构》课本KMP算法的理解
数据结构课上讲的KMP算法和我在ACM中学习的KMP算法是有区别的,这里我对课本上的KMP算法给出我的一些想法. 原理和之前的KMP是一样的https://www.cnblogs.com/wkfvaw ...
- 关于KMP算法的理解
上次因为haipz组织的比赛中有道题必须用到KMP算法,因此赛后便了解了下它,在仔细拜读了孤~影神牛的文章之后有种茅塞顿开的感觉,再次ORZ. 附上链接http://www.cnblogs.com/y ...
- KMP算法自我理解 和 模板
字符串 abcd abc abcd abc 匹配串 cdabcd 匹配串的 next 0 0 0 0 1 2: 开始匹配 abcd abc abcd abc cd abc d a,d 匹配失 ...
- 第十一章 串 (c3)KMP算法:理解next[]表
- kmp算法初步理解
123456789 abbdaxnds Next 01212 第三位看第二位b,第二位和第三位相同,都是b,所以第三位的next是第二位的next加1,即1+1=2 第四位看第三位b,第四位d与第 ...
- KMP算法中next函数的理解
首先要感谢http://blog.csdn.net/v_july_v/article/details/7041827以及http://blog.chinaunix.net/uid-27164517-i ...
随机推荐
- npm 安装 electron 出现的奇葩错误
起因 使用yarn安装electron有时稳定,在搭配别的框架时有时又出现无解的错误了,于是打开electron官网,发现: emm,似乎官方对npm情有独钟.于是我遵从官方旨意使用npm安装elec ...
- Map-->HashMap练习(新手)
//导入的包.import java.util.*;//创建的一个类.public class zylx1 { //公共静态的主方法. public static void main(String[] ...
- Natas14 Writeup(sql注入、sql万能密码)
Natas14: 是一个登录页面.源码如下. if(array_key_exists("username", $_REQUEST)) { $link = mysql_connect ...
- WxPython 4.0.4多线程访问UI
最开始做框架的时候的需求就是多线程访问UI,以前在.NET WPF使用MVVM和数据驱动很容易做到,在JavaSwing中使用另类的观察者模式也实现了.在WxPython中使用观察者模式直接程序崩溃, ...
- 题解 CF1304E 【1-Trees and Queries】
前言 这场比赛,在最后 \(5\) 分钟,我想到了这道题的 \(Idea\),但是,没有打完,比赛就结束了. 正文 题目意思 这道题目的意思就是说,一棵树上每次给 \(x\) 和 \(y\) 节点连 ...
- 动态规划-计数dp-Distinct Subsequences II
2020-02-06 17:01:36 问题描述: 问题求解: 非常经典的计数dp问题,思路就是统计以每个字符为结尾的个数,最后求和即可. dp[i] = sum of (dp[j]) 0 <= ...
- Android通知栏前台服务
一.前台服务的简单介绍 前台服务是那些被认为用户知道且在系统内存不足的时候不允许系统杀死的服务.前台服务必须给状态栏提供一个通知,它被放到正在运行(Ongoing)标题之下--这就意味着通知只有在这个 ...
- 如何使用WordPress搭建网站
1.空间的申请 阿里用户可以申请[阿里共享虚拟主机普惠版6元/年],虽然配置和空间不高,但也可以做个小站点的.当不满足当前配置的时候,随时可以进行升级,所以拿来练手还是比较合适的. 2.WordP ...
- Building Applications with Force.com and VisualForce(Dev401)(十):Designing Applications for Multiple Users: Building Business Processes that You Want
Dev401-011: Building Business Processes that You Want Course Objectives1.Describe the capabilities o ...
- [codevs1049]棋盘染色<迭代深搜>
题目链接:http://codevs.cn/problem/1049/ 昨天的测试题里没有打出那可爱的迭代深搜,所以今天就来练一练. 这道题其实我看着有点懵,拿着题我就这状态↓ 然后我偷偷瞄了一眼hz ...