KMP 算法简述

来源:互联网 发布:下载烈火软件 编辑:程序博客网 时间:2024/06/04 19:34

kmp算法是一个比较经典的字符串比较算法,现在学渣准备用最贴地气的方法简述一下,希望和大家共同学习。

1 字符串比较

 在本文中,主要用如图1的两个字符串进行比较。这是算法导论里的例子,上面的字符串我们称为T,下面的成为模式P

    

                   图1                                                                          图2

如图1所示,如果在比较到绿线所指的a和c时,发现两个字母不匹配,如果在朴素算法中,需要将P右移一位,重新进行对比,如图2

2规律

其实在这个匹配过程中,有一部分信息被丢掉了,因为如图1,T和P的红框部分的ababa已经完全匹配,完全可以向后移动3位,如图3所示,进行比较

这时发现,从这个位置开始比也是完全可行的,如果按照朴素算法,向后移动一位发现不匹配,再向后移动,会消耗大量的时间。


                      图3

3 前缀函数

如上所述,在字符串的匹配过程中,如何才能预知以上的这种规律呢,就是前缀函数,算法导论里叫π。在字符串的匹配过程中,模式P是提前预知的,于是我们讲对P进行惨无人道的压榨,获取其的一些信息用来组成π。

我们需要对2中的规律进行详细分析,我们需要的是神马规律,对于T而言,如果在判断到T[i]与P[q]时,两个元素不等时,我们需要一个信号,即这个T[i]和P的哪个元素相比较才是又快捷又不会丢失信息呢?例子中的a需要和P的第4个元素进行对比(我们假设这个数组从第1个元素开始),即我们认为我们已经重新匹配了P的三个元素了,我们只需要从第四个元素开始比较就行。因为我们已经对P进行了分析,那么我们可以定义一个数组(就是π),如现在我在图1中匹配了5个字母,我在π[5]中放一个3,代表如果T中的任何一部分能够和P的前5个元素进行匹配 ,如果第六个不匹配时,只需要匹配第π[5]+1个元素就ok,π[i]的意义就是,如果前i个元素都匹配,第i+1个元素不匹配,只需要用第π[i]个元素进行对比。例子中的是P的前3个元素和ababa的后三个元素完全匹配用算法导论里的书面语言就是:P3是能构成P5的真后缀的P的最长前缀(学渣用了好几分钟才看懂这几个中国字。。。)

如果大家能看懂上述的描述,对于前缀数组π而言,π[i]的意义是,P(π[i]) 是能构成Pi 的真后缀的P的最长前缀。书面的表达式是:

π[q] = max {k: k < q 且 Pk < Pq} (第二个<是包含符,学渣表示不会打这个符号)

4 求前缀数组

对于π[1],一定等于0,一个元素没有前缀。。。

前缀数组是指模式P的前缀数组(重要。。。),算法如下:

p = P.length

π[1]=0;            //第一个元素一定为0

k=0                  //相当于两个P在对比,一个是从k开始,一个是从q开始,k代表已经匹配好的元素

for q=2 to m    //直接从第二个元素开始计算

    while k > 0 and P[k+1] != P[q]    //最关键的一步如果第P[k+1] 和 P[q]不相等,则利用π的定义,而且前k个都已经匹配,π[k]代表用第π[k+1]个元素对比就行                  

k = π[k]

//到了此步的k,说明P[q]和P[k+1]是一定要进行对比的

     if P[k+1] == P[q]

         k=k+1

      π[q] = k   //


return π ....



0 0