KMP(MP)算法详解

Written with StackEdit.
由于CSDN服务器的维护,我迫不得已地用了和CSDN版本相近的StackEdit

KMP 算法,是一种字符串匹配的算法。当然,我们已经学过了一两种字符串匹配算法,先来稍微回顾一下。
首先是暴力匹配,也就是将串中每一个长度等于另一串的子串和另一串进行匹配。若两串的长度为 n m,那么其的时间复杂度显然是 O(nm)
然后是哈希。哈希在本质上是一种概率算法,实际上是采用了一种映射的方法,如果将所有被哈希之前的字串的集合设为 A ,而被哈希之后的字串的哈希值集合设为B,那么也就相当于定义了一个映射 Hash:AB ,注意这不是一个单射,因为在大多数的情况下,有 |A|<|B| 。当然,有很多方法改进,但是只有完美哈希使得它不再算一个概率算法,然而完美哈希本身的操作过于繁琐,一般适用于字串不变的情况,如编译器中的指令。实际上,哈希算法的本质和暴力是一致的,但是由于映射的存在,使得哈希算法要比较的东西就不那么多了,就像暴力算法中只抽样比几位一样,但是哈希算法相当于是在每一位中都抽一点点的样(有些时候不是这样),所以更为准确一些。其的时间复杂度为 Θ(n+mlogvMod) ,其中 v 是计算机所采用的进位制(如现在的一般采用二进制,不排除以后有更高进制的计算机,或者要求相关的交互题:)),Mod则是你所使用的模数(因为我们当时只学了一种哈希:-()。
好吧,回顾完了,我们来稍微了解一些关于 KMP 的东西。 KMP 的本质是暴力匹配的优化,而其有一个较为简单的版本, MP 。本文介绍时将先介绍 MP 算法,再比较 KMP MP 之间那一个 K 的不同。
考虑暴力算法,其思路大致是用指针 i j分别遍历两个串,然后当失配(即两个指针对应的字符不相等时)回到两个串“前面的位置”,也就是像回溯一样不断尝试。
但是,这样单纯地找,有时是不会有好结果的。如下所示,两个串 A B

A:abababc
B:ababc

其中,若在串 A 中找串B,那么第一次尝试匹配到 ababa 时,只有最后一位的 a c 不一样。但是,这时我们注意到,串 B 中有两个ab,所以当回溯时,我们并不用将串 A 中的指针i前移,而只需将 B 中的指针j前移到开头即可。若设 A=a1a2a3a4 B=b1b2b3b4 ,那么因为已经比较,所以自然有 a1=b1,a2=b2,a3=b3,a4=b4 ,于是又由于我们已知 b1=b3,b2=b4 ,那么就有 b1=a3,b2=a4 。所以,只需从原位置继续开始即可。
MP 算法正是基于这样的一种思想。倘若存在某个 [1,j]=[ij,i] ,那么我们定义 j=next(i) ,表示当在 i 位置的字符失配时应当跳到哪里。其的求法我们先不管,但是这样一来匹配就很好写了,代码这里略去,请自行查找资料。
那么,next(i)的求法又应当是怎样的呢?答案是:几乎和匹配一样!想想看, next(i) 的求解,不正相当于是用自己匹配自己吗?假如我们知道 next(i) ,那么我们能找到一个 j ,使得串S中有 Si+1=Sj+1 (当然,有时找不到,这时只需要设为一个特殊值就行了:))那么这样的话,就应当有 next(i+1)=j+1
这,就是 MP 算法的全套,至于 KMP 算法,请自行查阅资料。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值