我对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 ...
随机推荐
- Docker 技术系列之安装Docker Desktop for Mac
终于要进入到Docker技术系列了,感谢大家的持续关注. 为什么要选择Docker?因为Docker 轻巧快速,提供了可行.经济.高效的替代方案.举个例子,安装Nginx,Mysql,Redis等常用 ...
- Java 14 发布了,可以扔掉Lombok了?
2020年3月17日发布,Java正式发布了JDK 14 ,目前已经可以开放下载.在JDK 14中,共有16个新特性,本文主要来介绍其中的一个特性:JEP 359: Records 官方吐槽最为致命 ...
- Error: java.net.ConnectException: Call From tuge1/192.168.40.100 to tuge2:8032 failed on connection exception
先看解决方案,再看唠嗑,唠嗑可以忽略. 解决方案: 使用start yarn.sh启动yarn就可以了. 唠嗑: 今天学习Spark基于Yarn部署.然后总以为Yarn是让Spark启动的,提交程序的 ...
- drf 简介以及部分源码分析
目录 复习 drf框架 全称:django-rest framework 知识点 接口 restful接口规范 基于restful规范的原生Django接口 主路由:url.py api组件的子路由: ...
- Nginx | CentOS 8 安装Nginx详细教程
Nginx是一个web服务器也可以用来做负载均衡及反向代理使用, 目前使用最多的就是负载均衡,这篇文章主要介绍了centos8 安装 nginx Nginx是一种开源的高性能HTTP和反向代理服务器, ...
- 【2019多校第一场补题 / HDU6578】2019多校第一场A题1001Blank——dp
HDU6578链接 题意 有一串字符串,仅由 {0,1,2,3}\{0, 1, 2, 3\}{0,1,2,3} 组成,长度为 nnn,同时满足 mmm 个条件.每个条件由三个整数组成:l.r.xl.r ...
- 你需要了解的 HTTP Status Code
你需要了解的 HTTP Status Code Intro 现在前后端分离的开发模式越来越流行,后端负责开发对应的 API,前端只需要 关注前端页面的数据展示和前端逻辑即可. 对于前后端分离这种开发模 ...
- mysql两表合并,对一列数据进行处理
加班一时爽,一直加班~一直爽~ 欢迎收看http://www.996.icu/ 今天弄了下MySQL中两表合并的并且要处理一列数据,这列数据原来都是小写字母,处理时将这列数据改成驼峰命名的~~ 基本 ...
- 给社团同学做的R语言爬虫分享
大家好,给大家做一个关于R语言爬虫的分享,很荣幸也有些惭愧,因为我是一个编程菜鸟,社团里有很多优秀的同学经验比我要丰富的多,这次分享是很初级的,适用于没有接触过爬虫且有一些编程基础的同学,内容主要有以 ...
- mysql事务提交和回滚机制
应用场景: 银行取钱,从ATM机取钱,分为以下几个步骤 1 登陆ATM机,输入密码: 2 连接数据库,验证密码: 3 验证成功,获得用户信息,比如存款余额等: 4 用 ...