KMP算法学习

原创 2016年08月30日 18:56:34

简单模式匹配最坏复杂度在:O(n*m)
KMP可以牛到在O(n+m)的时间数量级上完成串的模式匹配操作。
核心来了:
改进:每当一次匹配过程中出现字符比较不等时,不需要回溯i指针(主字符串),而是利用已经得到的”部分匹配”的结果将模式向右”滑动”尽可能远的一段距离,继续进行比较。

所以核心在于,向右滑动多少距离怎么计算。
终于搞得懂了,记录一下。

设主串是S,模式串是P。
用i指针在S串中游动,j指针在P串中游动。不用考虑i,j是从0开始计数还是从1开始计数。任选一个,这里我选择从1计数。
也即:S1S2S3….Sn
P1P2P3….Pm
上面我们说,核心在于失配时,模式串尽可能向右滑动远的一段距离
这是感性的说法,用可量化的语言描述是:当S[i] != P[j]时,i指针不要回溯,而是想,S[i]和P[k]再比较,这样只需要针对模式串进行研究

以下是数学推导:

失配时,已经部分匹配的是:P1P2…Pj-1 = Si-j+1Si-j+2…Si-1

注意下标。
假设此时应与模式中第k个进行比较,必须要满足的条件是:
模式串中前k-1个字符的字串必须和S[i]前面k-1个字符匹配。
即:

      P1P2...Pk-1 = Si-k+1Si-k+2…Si-1  (1)

此时让S[i]与P[k]比较,所以部分匹配满足:

      Pj-k+1Pj-k+2…Pj-1 = Si-k+1Si-k+2..Si-1  (2)

这里的j仍是当前未回溯的j的值。其实,在失配时:

    P1P2...Pj-1 = Si-j+1...Si-1,上面只是选取一部分与(1)可联立方程。

所以由(1) (2)可以推导出:

      P1P2…Pk-1 = Pj-k+1Pj-k+2…Pj-1(*)

也就得到了在失配时,如何仅仅根据模式串自身就能找到k的公式了。

P[1]=P[jk+1]P[2]=P[jk+2]P[3]=P[jk+3]...P[k1]=P[j1]

左边序号是升序,右边也是升序。因此,寻找的k值是:失配字符之前前缀和后缀相等的最大长度+1

特别注意k的含义是:指向下一个与文本串比较的在模式串中的位置,而前缀和后缀相等是公共部分,长度+1后才是k的位置。

令next[j] = k,我们就得到了常用的函数:

next[j] = 0, 当j = 1时
next[j] = max{k|1 < k < j 且P1P2…Pk-1 = Pj-k+1Pj-k+2…Pj-1,此集合不空}
next[j] = 1,其他情况

再次说明:next[j] 表示的是当模式中第j个字符与主串中相应的字符失配时,在模式中需要重新与主串中该字符串进行比较的字符的位置。

所以是基于j指针进行k的寻找,j是失配时候的值。

有了next[j]函数,那么匹配过程就可以描述为:

假设以指针i和j分别致使主串和模式中正待比较的字符,令i的初值为1.

若在匹配过程中,Si = Pj,则i++,j++
否则失配,i保持不变,j回退到next[j],即: j = next[j].再比较Si和Pj
若回退到j为0,则表示第一个字符就失配,此时需要主串的下一个位置开始于模式重新开始匹配。

以后再补代码。

版权声明:本文为博主原创文章,未经博主允许不得转载。

改进的KMP算法

/*改进的字符串匹配算法 改进的KMP算法*/ #include #include #include int next[100];//全局变量 int KMP(char S[],char ...
  • silence2015
  • silence2015
  • 2016年02月22日 15:10
  • 1057

KMP算法 串的模式匹配算法优秀总结

转载大神的博客受益匪浅 这几天学习kmp算法,解决字符串的匹配问题,开始的时候都是用到BF算法,(BF(Brute Force)算法是普通的模式匹配算法,BF算法的思想就是将目标串S的第一个字符...
  • ltyqljhwcm
  • ltyqljhwcm
  • 2016年05月20日 12:21
  • 1283

从头到尾彻底理解KMP(转载自July)

从头到尾彻底理解KMP 作者:July 时间:最初写于2011年12月,2014年7月21日晚10点 全部删除重写成此文,随后的半个多月不断反复改进。 1...
  • wjy0330
  • wjy0330
  • 2014年09月26日 23:31
  • 1564

飘逸的python - 字符串的KMP匹配算法

首先我们来看一下字符串的朴素匹配. 可以想象成把文本串s固定住,模式串p从s最左边开始对齐,如果对齐的部分完全一样,则匹配成功,失败则将模式串p整体往右移1位,继续检查对齐部分,如此反复. #朴素...
  • u010180339
  • u010180339
  • 2014年11月10日 11:20
  • 4901

KMP算法中心思想

KMP是一种高效的字符串查找算法,主要用于在主串中查找一个特定字串(模板)出现的位置(或是否出现)。 朴素字符串查找算法主要是通过逐次比较来实现的,在主串中找到一个位置I和字串起始字符一样时,便顺...
  • yuxin8000
  • yuxin8000
  • 2015年08月13日 17:22
  • 806

KMP算法-Java实现

KMP算法之Java实现
  • qq_26411333
  • qq_26411333
  • 2016年06月09日 20:09
  • 2941

BF算法和KMP算法对比

BF算法和KMP算法     子串的定位操作通常被称作串的模式匹配,所谓的模式匹配即从较长的字符串S(主串)的pos位置处开始寻找字符串P(模式串)首次出现的位置,模式匹配算法经典的有BF算法和KMP...
  • Tsou_Joyce
  • Tsou_Joyce
  • 2014年03月07日 20:13
  • 1164

KMP及其改进算法

本文主要讲述KMP已经KMP的一种改进方法。若发现不正确的地方,欢迎交流指出,谢谢! KMP算法的基本思想: KMP的算法流程: 每当一趟匹配过程中出现字符比...
  • GarfieldEr007
  • GarfieldEr007
  • 2016年01月18日 15:44
  • 1643

拓展kmp算法总结

算法总结第二弹,上次总结了下kmp,这次就来拓展kmp吧。 拓展kmp算法是对KMP算法的扩展,它解决如下问题: 定义母串S,和字串T,设S的长度为n,T的长度为m,求T与S的每一个后缀的最长公共前...
  • dyx404514
  • dyx404514
  • 2014年12月09日 22:02
  • 8496

如果你看不懂KMP算法,那就看一看这篇文章( 绝对原创,绝对通俗易懂)

KMP算法之浅显易懂的阐述!
  • u011564456
  • u011564456
  • 2014年03月09日 20:32
  • 6238
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:KMP算法学习
举报原因:
原因补充:

(最多只允许输入30个字)