原创作者:Daniel
日期:2017.9.27
地点:大连理工大学软件学院
KMP算法包括两个过程:
1.计算模式的特征向量
int * next(string P ){
int m = P.length();
int* M = new int[m];
M[0] = 0;
for(int i = 1; i < m; ++i){
int k = M[i -1];
while(k > 0 && P[k] != P[i])
k = M[k - 1];
if(P[k] == P[i])
M[i] = k + 1;
else
M[i] = 0;
}
return M;
}
int KMPstring_match(const string & P, const string & T, int* next ){
int i = 0;
int j = 0;
while(T[i] != '\0' && P[j] != '\0'){
if(T[i ] == P[j]){
i++;
j++;
}
else{
if(j == 0)
i ++;
else
j = next[j - 1];
}
}
if( j == P.length())
return i - j;
else
return -1;
}
具体讲讲模式的特征向量的求法。
KMP算法实际上是根据模式自身的特点来简化传统模式匹配过程的,在传统配
过程中,每次匹配不满足时,都会将模式指针 p = 0,然后让目标上的指针 t ++,所
以,每匹配一次都会进行回溯,造成了效率低下,具体时间复杂度是:O(M*N);
下边是传统模式匹配C++代码:
int naive_string_match(string P, string T){
int p = 0;
int t = 0;
int plen = P.length();
int then = T.length();
while(P[p] != '\0'&& T[t] != '\0'){
if(P[p] == T[t]){
p++;
t++;
}
else{
p = 0;
t = t - p + 1 //为了将t移动到下一个匹配位置。
}
}
if(p >= plen)
return t - p;
else
return -1
}
特征向量 next()函数求法:
特征向量的分量n[i]如下定义:
1、n[0] = 0,对于 i > 0 的 n[I] ,n[i - 1] = k;
2、如果i > 0,并且 P[k] = P[i],n[i] = k + 1;
3、如果P[k] != P[i] , 令 k = n[k -1];
4、如果P[k] != P[i] && k == 0 , n[i] = 0;
在 i 位置匹配失败后,就直接从P[i - n[i - 1]]继续匹配,避免了回溯。
在模式走到结尾时 返回 EOF;
模式匹配成功返回 i - j;