kmp算法python实现
kmp算法python实现
kmp算法
kmp算法用于字符串的模式匹配,也就是找到模式字符串在目标字符串的第一次出现的位置
比如
abababc
那么bab在其位置1处,bc在其位置5处
我们首先想到的最简单的办法就是蛮力的一个字符一个字符的匹配,但那样的时间复杂度会是O(m*n)
kmp算法保证了时间复杂度为O(m+n)
基本原理
举个例子:
发现x与c不同后,进行移动
a与x不同,再次移动
此时比较到了c与y,
于是下一步移动成了下面这样
这一次的移动与前两次的移动不同,之前每次比较到上面长字符串的字符位置后,直接把模式字符串的首字符与它对齐,这次并没有,原因是这次移动之前,y与c对齐,但是y前边的ab是与自己的前缀ab一样,于是ab并不用再比较,直接从第三个位置开始比较,如图:
所以说kmp算法对于这种情况就直接使用当前比较字符之前的最长相同的前后缀,然后将前缀与上面的长字符串对齐,继续比较后面的字符串。
这里kmp算法中的一个重要点就来了,如何找到模式字符串中每位字符之前的最长相同前后缀呢
这里继续用一个例子举例:
下面的数字记录以该字符为结尾的最长前后缀相同子串的长度,先初始化为0,并且第一个字符下的数字确认为0
然后开始比较:
a与b不同,那么b下的数字也为0同理a与c不同,c下的数字也为0,接下来a与a对齐,如下
此时a与a相同,那么a下面的数字为1,也就是第二排字符串中当前比对的字符索引+1
接下来b与b相同,c与a不相同,那么此时上面的字符串不动,下面的字符串移动到当前比对位置即c的前一位的下方的数字的位置,如图:
移动前
c的前一位是b,b下方的数字是0,所以将下面字符串的第0位与之前的比对位置对其,即:
当前比对位置如箭头所示,然后继续向后比较,一直比到c与a:
此时c与a不相同,那么比较下面字符的前一个字符的下方数字的位置,如图
也就是位置为2的地方与上面比对位置对齐:
此时c与c相同,整个字符串自比对完成:
此时可能会没有理解为什么匹配不成功的时候要再比对其前一位字符下的数字的位置,那是因为这是要找到前一个字符位置下的最长相同前缀中的最长相同前缀,就举刚才的例子:
此时a前边是abcab,所以要找到abcab的最长相同前缀,就是ab,这时
然后再移动到ab与ab对其的位置继续比较即可
时间复杂度
简单来讲, 找到模式字符串中每位字符之前的最长相同前后缀的这个方法中,如果模式字符串的长度为m,那么上面的字符串的指向是一直向前移动的,下面字符串的整体也是一直向前移动的,最终移动的结果将会是长度为2m,所以比较次数也是最大为2m,时间复杂度为O(m)
kmp算法中,运用了找到模式字符串中每位字符之前的最长相同前后缀的这个方法的结果,然后使用类似的方法进行比较和移动,和上边的解释类似,如果这个要匹配的字符串长度为n,那最长的移动举例也超不过2n,所以总的时间复杂度为O(m+n)
具体代码
这里没有进行传入参数的验证,使用时还要注意。
def same_start_end(s):
"""最长前后缀相同的字符位数"""
n = len(s) #整个字符串长度
j = 0 # 前缀匹配指向
i = 1 # 后缀匹配指向
result_list=[0]*n
while i < n:
if j == 0 and s[j] != s[i]: # 比较不相等并且此时比较的已经是第一个字符了
result_list[i] = 0 # 值为0
i += 1 # 向后移动
elif s[j] != s[i] and j != 0: #比较不相等,将j值设置为j前一位的result_list中的值,为了在之前匹配到的子串中找到最长相同前后缀
j = result_list[j-1]
elif s[j] == s[i]: #相等则继续比较
result_list[i] = j+1
j = j+1
i = i+1
return result_list
def kmp(s,p):
"""kmp算法,s是字符串,p是模式字符串,返回值为匹配到的第一个字符串的第一个字符的索引,没匹配到返回-1"""
s_length = len(s)
p_length = len(p)
i = 0 # 指向s
j = 0 # 指向p
next = same_start_end(p)
while i < s_length:
if s[i] == p[j]: # 对应字符相同
i += 1
j += 1
if j >= p_length: # 完全匹配
return i-p_length
elif s[i] != p[j]: # 不相同
if j == 0: # 与模式比较的是模式的第一个字符
i += 1
else: # 取模式当前字符之前最长相同前后缀的前缀的后一个字符继续比较
j = next[j]
if i == s_length: # 没有找到完全匹配的子串
return -1
kmp算法python实现的更多相关文章
- KMP算法-Python版
KMP算法-Python版 传统法: 从左到右一个个匹配,如果这个过程中有某个字符不匹配,就跳回去,将模式串向右移动一位.这有什么难的? 我们可以 ...
- BF算法和KMP算法 python实现
BF算法 def Index(s1,s2,pos = 0): """ BF算法 """ i = pos j = 0 while(i < ...
- 字符串匹配的KMP算法——Python实现
#! /usr/bin/python # coding=utf-8 """ 基于这篇文章的python实现 http://blog.sae.sina.com.cn/arc ...
- 字符串匹配的kmp算法 及 python实现
一:背景 给定一个主串(以 S 代替)和模式串(以 P 代替),要求找出 P 在 S 中出现的位置,此即串的模式匹配问题. Knuth-Morris-Pratt 算法(简称 KMP)是解决这一问题的常 ...
- 字符串匹配算法之 kmp算法 (python版)
字符串匹配算法之 kmp算法 (python版) 1.什么是KMP算法 KMP是三位大牛:D.E.Knuth.J.H.MorriT和V.R.Pratt同时发现的.其中第一位就是<计算机程序设计艺 ...
- Python 细聊从暴力(BF)字符串匹配算法到 KMP 算法之间的精妙变化
1. 字符串匹配算法 所谓字符串匹配算法,简单地说就是在一个目标字符串中查找是否存在另一个模式字符串.如在字符串 "ABCDEFG" 中查找是否存在 "EF" ...
- 数据结构与算法-Python/C(目录)
第一篇 基本概念 01 什么是数据结构 02 什么是算法 03 应用实例-最大子列和问题 第二篇 线性结构 01 线性表及其实现 02 堆栈 03 队列 04 应用实例-多项式加法运算 05 小白专场 ...
- 扩展的KMP算法图解
扩展的KMP算法,可以在Ο(n + m)的时间复杂度内计算出模板串与文本串的每一个后缀的最长公共前缀,即LCP(T[i:n],P). KMP算法所解决的单模板字符串匹配问题,求得的匹配点是LCP = ...
- 字符串模式匹配算法系列(二):KMP算法
算法背景: KMP算法是由Donald Knuth和Vaughan Pratt于1970年共同提出的,而James H.Morris也几乎同时间独立提出了这个算法.因此人们将其称作“克努特-莫里斯-普 ...
随机推荐
- SpringBoot(8) SpringBoot过滤器Filter
1.SpringBoot启动默认加载的Filter characterEncodingFilter hiddenHttpMethodFilter httpPutFormContentFilter re ...
- NET Core微服务之路:弹性和瞬态故障处理库Polly的介绍
前言 上一节中我们介绍了Ocelot的常见使用配置,通过json配置文件,实现API网关的请求处理.和一个使用DownStream扩展下游中间件,来实现Http转RPC的简单实现,功能不算强大,但可以 ...
- vue开发中vue-resource + canvas 图片压缩、上传、预览
1.使用vue-resource上传,也可以自定义ajax上传: 2.使用<input type="file" @change="submit()" na ...
- Python面向对象基础:设置对象属性
用类存储数据 类实际上就是一个数据结构,对于python而言,它是一个类似于字典的结构.当根据类创建了对象之后,这个对象就有了一个数据结构,包含一些赋值了的属性.在这一点上,它和其它语言的struct ...
- Go基础系列:惰性数值生成器
惰性数值生成器是指在需要的时候才生成下一个数值,不需要的时候就卡在那.这和python的列表推导表达式类似.惰性生成器的好处是不会一次性将全部结果返回或放进内存,而是每次只返回一个,这样不会在某一时刻 ...
- 分布式系统监视zabbix讲解二之邮件报警通知--技术流ken
概述 在上一篇博客<分布式系统监视zabbix讲解一技术流ken>中已经详细讲解了如何安装zabbix,本篇博客将详细讲解如何使用zabbix监控另外一台主机,并实现email报警通知机制 ...
- 【转载】C#将图片以二进制流的方式存入数据库
在C#开发应用程序的过程中,图片一般会存放在文件系统中,当然图片也可以二进制的方式存放到数据库中,不过一般不建议存放在数据库中,因为图片占用的空间还是挺大的,特殊情况下可以考虑将图片存在数据.此文将介 ...
- 高德地图Javascript API设置域名白名单
在涉及到GPS地图相关应用的开发过程中,我们需要在高德开放平台注册相应的账号,并设置好相应应用来获取调用的Key值,该Key值直接放入到网站前端页面,针对任何人来说都可看到,因此我们防止他人盗用你的K ...
- IIS发布网站 报错500.19 错误解决过程记录
首先先报上我的环境 WindowsServer 2012 IIS 8.5 网站是FrameWork 4.0 发布网站后浏览,报错信息如下: 解决过程记录如下: 1.看到这个问题首先想到的是权限问题,设 ...
- DirBuste 使用
https://sourceforge.net/projects/dirbuster/ 官网下载 记得安装java 运行环境 这是扫描 443 端口的数据 也可以自己写字典规则 在选择模糊查询时 下面 ...