中间跳过了几章,先看自己认为比较容易看懂了几章,结果发现,证明真是难呀。虽然没有怎么看过其他的算法书,但是觉得算法导论虽然在证明,把问题形式化方面稍微有点罗嗦了,但是感觉还是不错了,它不会直接抛给你一个最有效的算法,然后直接跟你讲,它会从最朴素的算法逐渐讲更有效率的算法,这样让读者对问题有更清晰的把握,而且有些高效率的算法往往是建立在朴素的算法上的。字符串匹配就是这样,朴素算法-自动机识别法-KMP算法。Rabin-Karp算法看得我有点头昏脑胀,暂时先放一下。
字符串匹配问题问题很明白。就是给定模式串P,去匹配串T中找P是否出现,返回匹配时T位置的偏移。
我们设P长度为m, T长度为n , Σ 字母表
1.朴素匹配算法就是从T的第一个字符逐个跟P比较,当出现不匹配时,向右移动一位,在重新和P开始比较,T中的每一位都有机会和P从头开始比较,但它的效率并不高,T中的n-m+1位都要比,而且在此位进行匹配时最坏情况下都要比较m个字符,所以最坏情况下运行时间是(n-m+1)*m
如何改进呢,就是过滤掉那些无效的偏移。
2.自动机法就是利用构造的转移函数,一步过滤掉了所有的无效偏移,但是构造自动机转移函数的代价可能会比较大。下面简要的说明一下自动机,自动机算法的证明还是看得比较明白,后面KMP算法的证明hold不住了。
关于自动机的定义大家看书,或者随便找本编译原理的书都有。有限自动机M(Q,q0,A,Σ,δ)
在这里构造的自动机是基于模式P构造的,
状态集合Q一共有m+1个状态,状态为0,1,2,3,4....m , q0=0为起始状态,A=m为接受状态。 δ为状态p遇到字符a转移到状态 q的一个映射。 δ(p,a)=q;而在自动机字符匹配里我们把这个转移函数定义为 δ(p,a)=q=σ((Pp)a),其中Pp表示P的长度为p的前缀。
σ() 函数为后缀函数,它的定义是 σ(x) 是字符串x的后缀模式P的最长前缀的长度。 有点拗口,举例如下:
P:a b a b a c a
σ(abdcaba)=3 ,因为x a b d c a b a <