KMP模式匹配算法

KMP模式匹配算法改进:https://blog.csdn.net/TinnCHEN/article/details/93472761

意义:当子串有多个相同部分时,与朴素模式匹配算法相比,大大减少了循环次数。时间复杂度由O((n-m+1)*m)变为O(n+m)。

重点:对用于匹配的子串的next数组的构建。next数组表示若当前位不匹配我们该从第几位开始重新比较。

next数组举例说明:
我们用 j 来表示子串中第几位,为方便我们从1开始计数。

eg1:当子串无重复时
子串abcdx
1、j = 1,next[1] = 0;
2、j = 2, j到j -1 之间为a,因此只有一位next[2] = 1;
3、j = 3, j到j -1 之间为ab, 且 a != b, 因此next[3] = 1;

我们可以得到next数组01111。

eg2: 当子串有重复时
子串:abcabx
1、j = 1,next[1] = 0;
2、j = 2, j到j -1 之间为a,因此只有一位next[2] = 1;
3、j = 3, j到j -1 之间为ab, 且 a != b, 因此next[3] = 1;
4、j = 4, j到j -1 之间为abc, 且 a != c, 因此next[4] = 1;
5、j = 5, j到j -1 之间为abca, 且 a == a, 因此next[5] = 2;
6、j = 6, j到j -1 之间为abcab, 且 ab == ab, 因此next[6] = 3;

具体代码实现:

void GetNext(string t, int *next){
     int i,j;
     i = 1;     //i表示后缀中最新需要比较的字符
     j = 0;     //j表示前缀中需要与后缀i比较的字符
     next[1] = 0;
     /*
     情况1:j == 0, 
     除了第一次进入循环意味着最新的比较位与前缀任一位置均不相同,
     j回溯到了next[1]。
     
     情况2:t[i] == t[j], 意味着i与前缀中的某一位j匹配上了,
     所以若下一个i(也就是代码中的++i)在匹配过程中发生了不匹配现象,
     可以直接从前缀的下一位(++j)处重新进行匹配,不用从头匹配。
     */
     while( i < t.size()){
        if( j == 0 || t[i] == t [j]){  
           ++i;
           ++j;
           next[i] = j;
        }
        else
           j = next[j]; //若不相等,则跳转到上一回溯位置看是否相等。
      }
}

int Pos_KMP(string s, string t, int pos){
   int i = pos;
   int j = 1;
   int next[1000];
   GetNext(t, next);
   while(i <= s.size() && j <= t.size()){
        if( j == 0 || s[i] == s[j]){
            ++i;
            ++j;
        }
        else
           j = next[j];  //此处是与朴素模式匹配算法不同处,不用每次都从第一位开始比较
    }
    if( j > t.size())
       return i - t.size();
    else
       return 0;
}

你可能感兴趣的:(数据结构)