Lec2-KMP算法学习

之前上数据结构课时没有学到,现在补起来。

 Ref:严蔚敏版《数据结构》上的讲解(浅显易懂)

 

http://www.ics.uci.edu/~eppstein/161/960227.html

 

 

子串的定位操作Index(S,T,pos)通常称作串的模式匹配(其中T称为模式串)。传统的字符串匹配算法如下:

 


0

1

2

3

4

5

6

7

8

9

10

11

 

b

a

n

a

n

a

n

o

b

a

n

o

index=0

X

 

 

 

 

 

 

 

 

 

 

 

index=1

 

X

 

 

 

 

 

 

 

 

 

 

index=2

 

 

n

a

n

X

 

 

 

 

 

 

index=3

 

 

 

X

 

 

 

 

 

 

 

 

index=4

 

 

 

 

n

a

n

o

 

 

 

 

index=5

 

 

 

 

 

X

 

 

 

 

 

 

index=6

 

 

 

 

 

 

n

X

 

 

 

 

index=7

 

 

 

 

 

 

 

X

 

 

 

 

index=8

 

 

 

 

 

 

 

 

X

 

 

 

index=9

 

 

 

 

 

 

 

 

 

X

 

 

index=10

 

 

 

 

 

 

 

 

 

 

n

X

index=11

 

 

 

 

 

 

 

 

 

 

 

X

由于在比较过程中指针 i 多次回溯, 所以时间复杂度在最坏时时O(m*n)。

KMP算法可以将传统字符串匹配算法的复杂度(O(m*n))提升到O(m+n),其中n为target(主串)的长度,m为 pattern(子串)的长度。空间复杂度为O(m)。

1.KMP的原理

其改进在于,每当一趟匹配过程中出现字符比较不等时,不需回溯 i 指针,而是利用已经得到的“部分匹配”的结果将模式向右“滑动”尽可能远的一段距离后,继续进行比较。

 

 

2. next函数

 next函数给出了在比较到当前字符时,如果不匹配,前面的字符应相当于已经比较过的位数。

 当匹配过程中出现不相等时,如果不要回溯指针,而是从此位开始继续比较,则需要next函数来知指明要和模式串(子串)的哪一位进行比较。

例如对于模式串acae,next(4)=2.  即当第四位匹配失败时,一定满足... ak-3 ak-2 ak-1 = a1 a2 a3 ...(字符串下标从1开始)

而acae,满足a(2)=a(0) ,则next(3)=1;若为abcd,则next(3)=0,表示从子串的第一个a开始比较。(所有下标包括next函数均从1开始标号)

a  c  a  c  a  e

|  |  |   !

a  c  a  e

            |->遇到不匹配(a!=e),从不匹配位继续比较,设当前母串标号为k,子串标号为j,当满足ak-i... ak-2 ak-1  = a1 a2 a3 ...ai时,next(j)=i。而ak-i... ak-2 ak-1 ak-1 一定是母串和子串的已匹配部分,故aj-i... aj-2 aj-1 aj-1 =  ak-i... ak-2 ak-1 ak-1

此例中则有next(4)=2.

 

 

 

 

 

 


 

 

3. next函数的计算

 KMP算法是在已知模式串的next函数的基础上执行的,那么,如何求得模式串的next函数值呢?

从上述讨论可见,此函数值仅取决于模式串本身而和相匹配的主串无关。我们可以从分析其地你故意出发用递推的方法求得next函数值。

由定义得知

    next[1]=0

设next[j]=k,这表明在模式串中存在下列关系:

    ‘p1...pk-1' = 'pj-k+1...pj-1'

其中k为满足1<k<j的某个值,并且不可能存在k'>k满足此等式。此时next[j+1]=?可能有两种情况:

 (1)若pk=pj,则表明在模式串中

    ‘p1...pk' = 'pj-k+1...pj'

 并且不可能存在k'>k满足登时,这就是说next[j+1]=k+1,即

    next[j+1]=next[j]+1

(2) 若pk!=pj,则表明在模式串中

     ‘p1...pk' != 'pj-k+1...pj'

下面部分是关键!

 此时可把求next函数值的问题看成是一个模式匹配的问题,整个模式串既是主串又是模式串,而在当前的匹配中已有

 (放在下一篇中)

 

 

此时只能在patternk+1个子符组所的子串中找到相应的next函数,h=next(k),如果此时pattern[h+1]==pattern[j+1],overlay(j+1)=h+1否则重复(2)过程.

 


 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2011-04-21 16:12  Avril  阅读(465)  评论(0编辑  收藏  举报