KMP学习笔记

时间:2020-12-12 17:56:15

功能

字符串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[]=;f[]=;
for (int i=;i<m;i++)
{
j=f[i];
while (j&&s[i]!=s[j]) j=f[j];
f[i+]=(s[i]==s[j]?j+:);
}
}

匹配函数:

输入

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=;
for (int i=;i<n;i++)
{
while (j&&s[j]!=t[i]) j=f[j];
if (s[j]==t[i]) j++;
if (j==m) return i-m+;
}
}