KMP,模式匹配算法

 

        我们经常会遇到一种情况是匹配两个字符串,看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

 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;
}

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

原文地址:https://www.cnblogs.com/xiaoyi115/p/3620565.html