KMP算法

一种字符串比对算法,寻找存在于长字符串中的子串,由Knuth、Morris、Pratt三个同时提出来。

算法的基本思路是:

假设有序列seq(长度为m)和子序列subseq(长度为n),
首先遍历序列seq,找到subseq[0]第一次出现在seq中的位置k;

然后顺次比较subseq[j](0<j<n)与seq[i](k<i<m), 即比较以subseq[0]开头长度为j的序列subseq[0,j]
和以seq[i-1]结尾长度为j的序列seq[i-j,i](此处之所以选择用i而不是k来描述seq的片段,是想通过序列片段
而不是单个字符进行移动,继而减少移动次数):

若在j==n-1时,每个元素都相等,则定位了一个子序列,重复上面的过程即可找到所有子序列的分布位置,

若对某一特定的j(0<j<n)使得subseq[j] <> seq[i], 这时则宣告最初找到的k不合意(应该后移),无法继续
延伸,这时需要调整j的值, 继而影响到k的值。为了调整后,依然满足subseq[0,j'] == subseq[i-j',i],就
要求j'应该满足subseq[0,j']==subseq[j-j',j],同时最佳j'应该是满足这个条件的最大值且j' <> j, 使
得能继续参与匹配的序列最长。当然也存在不能找到合适的j'的情况,这时另j'等于0, 而增加i的值直到再次碰到
subseq[0]。同时,我们可以看到j'的取值只取决于subseq,因此我们可以提前构建出这样一个索引数组来指导错误匹配之后的移动。

索引数组index的构建:
索引数组的构建就是对字符串进行自我扫描的过程,每个值都可以递归的由其前一个位的值得出。
假设index[j-1] = k, 只要index[k] == index[j],index[j] = index[j-1]+1, 因为index[0,k] = index[j-k,j], 所以index[0,k+1] == index[j-k, j+1]。若index[k] != index[j],这时可以回溯到index[index[j-1],若依然不满足则递归index[index[index[j-1]],直到满足或取值为0, 由此得到index数组。

假设seq = 'abaebacddebacdbace', subseq = 'bace'.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
a b a e b a c d d e b  a  c  d  b  a  c  e

b a c e
0 1 2 3

当k=1时,subseq[0] == seq[k],
然后subseq[1] == seq[2], subseq[2] != seq[3], 这时需要调整j的值,使得subseq[0,j']依然等同于
seq[i-j'+1,i], 这就使得j'要满足使得subseq[0,j]的前j'的字母和后j'个字母完全相同, 由于没有合适的,
j'取值0,此时继续增大i的值直到再次在seq里遇到subseq[0], 重复以上过程。这个例子比较特殊没有利用到算法的优势。
若子序列不存在重复,用KMP算法和用下面的一个bruteforce程序效果应该相差不大, 另外python的find和index在处理字符串时速度也很可观。

另一个例子是matrix67上的, 大家可过去参考下。

参考:http://www.matrix67.com/blog/archives/115

http://stackoverflow.com/questions/425604/best-way-to-determine-if-a-sequence-is-in-another-sequence-in-python

--------------------------- Bruteforce mathod: --------------------------- def index(subseq, seq): ''' index(subseq, seq) -->a list of numbers or -1 Return an index of [subseq] in the [seq]. Or -1 if [subseq] is not a subsequence of [seq]. The time complexity of the algorithm is O(n*m), where n, m = len(seq), len(subseq). >>>index('12', '0112') [2] >>>index([1,2], [011212]) [2, 4] >>>index('13', '0112') -1 ''' i, n, m = -1, len(seq), len(subseq) index = [] try: while True: i = seq.index(subseq[0], i+1, n - m + 1) if subseq == seq[i:i+m]: index.append(i) except ValueError: return index if len(index) > 0 else -1 def subseqInSeq(subseq, seq): ''' subseqInSeq(subseq, seq) ---> list or -1 The same as index. ''' indexList = [] m = len(subseq) subseqRepla = '*' * m while subseq[0] in seq: index = seq.index(subseq[0]) if subseq == seq[index:index+m]: indexList.append(index) seq = seq.replace(subseq, subseqRepla, 1) else: seq = seq.replace(subseq[0], '*', 1) return (indexList if len(indexList) > 0 else -1) def main(): print index('ab', 'abcdab') print subseqInSeq('ab', 'abcdab') ------------------------------------------------------------ KMP def compute_prefix_function(p): m = len(p) pi = [0] * m k = 0 for q in range(1, m): while k > 0 and p[k] != p[q]: k = pi[k - 1] if p[k] == p[q]: k = k + 1 pi[q] = k return pi def kmp_matcher(t, p): n = len(t) m = len(p) pi = compute_prefix_function(p) q = 0 for i in range(n): while q > 0 and p[q] != t[i]: q = pi[q - 1] if p[q] == t[i]: q = q + 1 if q == m: return i - m + 1 return -1

KMP字符串比对算法理解相关推荐

  1. 基于kmp字符串模式配算法的病毒感染检测问题

    本文记录了数据结构习题解析与实验指导(李冬梅)的实验4. 以下是实验内容 文章目录 1 问题描述 2 基本思想 3 KMP算法 4 Kmp代码主体部分 5 全部代码 6 nextval数组 1 问题描 ...

  2. KMP算法理解(转)

    (作者matrix67) KMP算法是拿来处理字符串匹配的.换句话说,给你两个字符串,你需要回答,B串是否是A串的子串(A串是否包含B串).比如,字符串A="I'm matrix67&quo ...

  3. kmp字符串查询算法

    kmp字符串查询算法 1 普通的字符串查询 普通的字符串查询是遍历被查找的字符串,然后和key字符串进行匹配,如果不一致,则,被查找的字符串+1,继续向下遍历. 代码如下: private stati ...

  4. 通过算法理解,把字符串转换成整形数字

    字符串转数字 先理解ASCII码规则 计算机中的字符包括数值.英文字母.标点符号.制表符号及其他符号.每一个字符都用一个特定的二进制代码来表示,这就是字符的编码.目前,字符编码采用的是美国信息交换标准 ...

  5. KMP字符串模式匹配详解

    KMP字符串模式匹配详解 KMP字符串模式匹配通俗点说就是一种在一个字符串中定位另一个串的高效算法.简单匹配算法的时间复杂度为O(m*n);KMP匹配算法.可以证明它的时间复杂度为O(m+n).. 一 ...

  6. 【ZOJ3587】Marlon's String——白四爷×KMP 白濑肆の算法完全解读KMP篇 KMP来袭第二弹前缀什么的果然最讨厌了!【1.0%达成!】

    #include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> ...

  7. KMP字符串模式匹配详解(zz)

    刚看到位兄弟也贴了份KMP算法说明,但本人觉得说的不是很详细,当初我在看这个算法的时候也看的头晕昏昏的,我贴的这份也是网上找的. 且听详细分解: KMP字符串模式匹配详解 来自CSDN     A_B ...

  8. KMP中next数组的理解

    next数组是KMP的核心,但对于next数组我们总是有时候感觉明白了,但有时候又感觉没明白,现在我就说下我自己对KMP中next数组的理解,首先next[i]上的数字的意义,next[i]表示的是当 ...

  9. KMP字符串模式匹配

    KMP 字符串基本概念 字符串 S:无特殊说明,字符串仅由26个小写字母'a'-'z',并用大写字母表示一个字符串 S="abcd" |S|:表示一个字符串的长度 |S|=4 S[ ...

最新文章

  1. npm安装出错Unexpected end of input at 1:2307
  2. python_控制台输出带颜色的文字方法
  3. CentOS7修改网卡名称为eth格式
  4. CRNN:端到端不定长文字识别算法
  5. uCOS-II任务的挂起和恢复
  6. consul历史版本下载地址
  7. PHP(三)——PHP基础知识
  8. shell数值大小的比较
  9. 新网站SEO要做的事情有哪些
  10. compilation targetFrameworkMoniker=.NETFramework,Version=v4.0
  11. 蓝桥杯 ALGO-115 算法训练 和为T Java版
  12. eclipse 如何查看Java源码
  13. psp3000 刷机
  14. Python文件转换为exe文件,可执行文件方法
  15. java生成pdf表格并插入图片
  16. [深度学习论文笔记]UCTransNet:从transformer的通道角度重新思考U-Net中的跳跃连接
  17. 566页19万字区级一网通办政务服务应用平台建设项目方案书
  18. 微信实时给服务器发送gps位置,你知道吗?微信聊天发原图暴露你的位置信息
  19. 知道你的成绩单是怎么打印的吗?超长Excel表格1页打印,拯救A4纸
  20. “芒果数据库”————mongodb分片全集和管理

热门文章

  1. 【Python】Sklearn加载load_digits样本数据集
  2. Winform下的键盘事件
  3. tp3.2部署在nginx主页正常,其他页面404问题解决方式
  4. 【译】怎样处理 Safari 移动端对图片资源的限制
  5. CyberArk:被忽略的特权账号管理已进入蓝海
  6. 一道笔试题引发的Promise笔记
  7. 诚通网盘会员很坑的,升级会员的人要注意
  8. 关于telnet: connect to address 190.168.6.6: No route to host 报错处理
  9. socket 编程原理1
  10. 为什么大学感觉学编程很难?原因有这三点。