Bing's Blog

胡言乱语,不必当真。

KMP算法学习

简单模式匹配最坏复杂度在: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,则表示第一个字符就失配,此时需要主串的下一个位置开始于模式重新开始匹配。

以后再补代码。

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011240016/article/details/52372086
文章标签: 算法 kmp
个人分类: 算法学习
想对作者说点什么? 我来说一句

KMP算法学习教程KMP算法学习教程

2011年05月19日 284KB 下载

K M P 算 法 . p p t

2011年08月10日 2.29MB 下载

KMP算法算法 KMP算法 KMP

2010年05月22日 1KB 下载

KMP算法详解 KMP算法详解

2010年08月10日 33KB 下载

没有更多推荐了,返回首页

不良信息举报

KMP算法学习

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭