KMP学习笔记

功能

字符串T,长度为n。

模板串P,长度为m。在字符串T中找到匹配点i,使得从i开始T[i]=P[0], T[i+1]=P[1], . . . , T[i+m-1]=P[m-1]

 

KMP算法先用O(m)的复杂度对模板串进行处理,然后O(n)进行匹配。总时间复杂度O(m+n)

 

注意失配函数f[i]为第i位处不能匹配时应当转向检查第f[i]位是否匹配:

 

比如模板串:

0

1

2

3

4

5

6

A

B

B

A

A

B

A

 

得到的失配函数为:

0

1

2

3

4

5

6

7

0

0

0

0

1

1

2

1

 

也即是说如果在模板串第5位失配,即当前位匹配不成功:

字符串

X

X

A

B

B

A

A

K

X

模板串

 

 

A

B

B

A

A

失配

 

 

那么根据失配函数f[5]=1,转移到1,表示已经匹配好一位,相当于模板串整体右移,但当前匹配的位置不变,然后继续匹配。

字符串

X

X

A

B

B

A

A

K

X

模板串

 

 

 

 

 

 

A

 

 

 

失配函数另一种用途:如果P存在循环节,f[i]为前一个循环节对应字符的位置。比如ABCABC,那么P[4]=B,而f[5]=2,也就是P[1]=B。

用途:计算字符串循环节长度。

 

构造失配函数:

s为模板串,f为待构造的失配数组,开始时为空

void getFail(char *s,int *f)
{
    int m=strlen(s),j;
    f[0]=0;f[1]=0;
    for (int i=1;i<m;i++)
    {
        j=f[i];
        while (j&&s[i]!=s[j]) j=f[j];
        f[i+1]=(s[i]==s[j]?j+1:0);
    }
}

匹配函数:

输入

t:文本,一大串字符串

s:模板,待匹配的模板

f:失配数组,一开始为空,函数过程中调用失配数组构造函数

输出

t字符串中模板第一次出现的位置(从0开始)

int find(char *t,char *s,int *f)
{
    int n=strlen(t),m=strlen(s);
    getFail(s,f);
    int j=0;
    for (int i=0;i<n;i++)
    {
        while (j&&s[j]!=t[i]) j=f[j];
        if (s[j]==t[i]) j++;
        if (j==m) return i-m+1;
    }
}

 

posted @ 2015-02-13 18:25  zhyfzy  阅读(189)  评论(0编辑  收藏  举报