KMP模式匹配算法
例:
a="abacdaabacdab"
b="abacdab"
a[i-j+1..i]与b[i..j]相等,随着i增加,j相应的变化,现在比较a[i+1]和b[i+1],若a[i+1]==b[i+1],则i++,j++;否则,若a[i+1]!=b[i+1],调整j的位置,使得 a[i-j+1..i]与b[i..j]保持匹配并且a[i+1]==b[i+1]。如何调整呢?j'要满足b[1..j]中的头j‘个字符与尾j'个字符完全相等,这样变了之后能继续保持i和j的性质,j'越大越好。直到j=m-1时,即b所有字符都匹配,则可返回位置。
若知道int *p,即不等时要退回的位置,可以编写代码如下:
int KMPmatch(char* a, int n, char* b, int m, int* p)
{
int j=0;
for(int i=0; i<n; i++)
{
while(j>0 && a[i] !=b[j])
j=p[j-1];
if(j==m-1)
return i-j;
if(a[i] == b[j])
j++;
}
return -1;
}
现在的问题是怎么求出这个int* p。其对于b的前i个字符,找出前i个字符的头j个与尾j个字符相同的个数。我们可以通过p[1..i]推出p[i+1]。即若b[i+1]=b[j+1],则p[i+1]=p[i]+1;若不等,则将j退回到p[j],再比较是否相等,直到b[i+1]=b[j+1]或j=0,这时p[i]=j。
void KMPfeature(char* b, int n, int* p)
{
p[0]=0;
int j=0;
for(int i=1; i<n; i++)
{
while(j>0 && b[j]!=b[i])
j=p[j];
if(b[j] == b[i])
j++;
p[i]=j;
}
}
测试代码如下:
#include <iostream>
using namespace std;
int main()
{
char* a="abababababababcababababbabcad";
char* b="ababababb";
int n= strlen(a);
int m= strlen(b);
int* p = new int[m];
KMPfeature(b, m, p);
cout << KMPmatch(a, n, b, m ,p)<< endl;
system("pause");
return 0;
}
我们看到,算法需要额外的m个空间来存储特征。m<<n时或要找出b在多个字符串中的位置时使用。
posted on 2011-09-23 19:10 Lovell Liu 阅读(194) 评论(0) 编辑 收藏 举报