KMP,模式匹配算法

时间:2023-01-13 06:12:43

 

        我们经常会遇到一种情况是匹配两个字符串,看strPar中是否含有str子串,如果有则返回子串在父串strPar中的位置,如果不存在则返回false.

        很明显,我们可以通过暴力求解的方式解决该问题。即从strPar第一个字符和子串进行比较,若成功则返回第一个0,若不成功,再第二个字符开始比较,这样的时间复杂度为O(M*N).可以看出,这个复杂度是相当高的,那么我们有没有一种复杂度会降低呢?显然,有一种叫做KMP算法可以大大降低复杂度O(M+N)。该算法通过记忆的方式,避免了很多无用功。

       比如字符...p1,p2,p3.....p‘,p'',p'''...

       假设p1,p2和p',p''是一样的,当我们进行比较的时候若在p'''比较失败,只需推到p3与父串进行比较即可,因为他前面的肯定是相同的。同时父串并不需要倒退。

       那么到底怎么退,退多少呢?

        这就需要有一个记忆数组,比如abaabcac

KMP,模式匹配算法

 1 void getNext(const char* str,int next[]){
2 int i=0,j=-1;
3 next[i]=j;
4 assert(str);
5 while(i<(int)strlen(str)){
6 if(j==-1||str[i]==str[j]){
7 i++,j++;
8 next[i]=j;
9 }
10 else
11 j=next[j];
12 }
13 }

得到了next数组之后,通过strPar和str比较。若相同则i++,j++;否则str往后退,即j=next[j];

int Index(const char* strPar,const char* str,int next[]){
int i=-1,j=-1;
assert(strPar
&&str);
int m=strlen(strPar),n=strlen(str);
while(i<m&&j<n){
if(j==-1||strPar[i]==str[j])
i
++,j++;
else
j
=next[j];
}
if(j==strlen(str))
return i-j;
else
return -1;
}

     版权所有,欢迎转载,但是转载请注明出处:潇一