KMP总结

总结

  1. 详细原理网上一大堆,这里只简单的总结一下自己的理解
  2. KMP匹配前需要的有主串a,模式串b,数组next
  3. 普通匹配会浪费时间,比如匹配好了一大串字符了,最后一个不匹配,下一次匹配要从这次匹配主串的起点的下一个字符开始匹配,而实际上刚刚匹配好的一大串字符,可能不需要再匹配
  4. 这里先为主串分配指针i,为模式串分配指针j
    • 普通匹配就是i会回溯,j也会回溯(第3点)
    • KMP匹配利用数组next让i不需要回溯,j回溯
  5. 数组next和模式串一一对应,记录当模式串某个字符不匹配时,j回溯的位置
    • 比如b="abcabd",匹配时a[i]='c'和b[j]='d'不匹配,next[j]=2,这时j从5回溯到2,因为前缀都有"ab"不需要在匹配一次
  6. 构造数组next的函数getNext,原理我自己也很难说通,都是结合代码来熟悉
    • 构造过程是模式串b进行自我匹配,为模式串b分配指针i和指针j

    • next[j]要回溯到哪里,取决于前缀相同位数

    • i<b.length()-1作为循环结束条件:两个字符匹配了是确定下一个字符的回溯位置

    • 如果匹配上了,指针i和指针j前进后,确定next[i]=j

    • 如果当前两个字符匹配了,b[i]==b[j],那么我们就能确定当下一个字符b[j+1]不匹配时j要回溯到哪里(next[i]==j),因为前缀相同才能匹配到当前位置,j+1不匹配,那就回溯到上一个前缀相同的位置

    • 如果匹配不上,指针j回溯

      • 回溯过程,可能回溯到next[0],这是 j==-1 说明指针j回溯到0时也没和b[i]匹配上,所以指针i和指针j前进
      • j==-1 进入匹配上了的循环是因为,匹配到i-1时已经确定了i的回溯位置,所以在匹配i的时候,是为i+1找回溯位置
      • 都可以++i,++j是因为j+1后,j=0,假设i=3,在KMP匹配中,b[3]不匹配时,指针j回溯到b[0]再进行匹配
  7. kmp匹配和求next数组的过程差不多
    • 主串a的指针i和模式串的指针j都是从0开始
    • 如果匹配上了,指针i和指针j前进
    • 如果匹配不上,指针j回溯
    • 指针j回溯到-1,说明指针j回溯到0时也没和主串匹配上,主串上的a[i]和模式串任何一个字符都不匹配,所以指针i和指针j前进

代码

#include <iostream>
#include <vector>
#include <string>
using namespace std;
void getNext(string b, vector<int>& next) {
    int i = 0;
    int j = -1;
    next[i] = j;
    while (i < b.length() - 1) {
        if (j == -1 || b[i] == b[j]) {
            ++i;
            ++j;
            next[i] = j;
        }
        else  j = next[j];
    }
}
int KMP(string a, string b, vector<int> next) {
    int i = 0, j = 0;
    while (i < a.length() && j < (int)b.length()) {
        if (j == -1 || a[i] == b[j]) {
            ++i;
            ++j;
        }
        else j = next[j];
    }
    if (j == b.length()) return i - j;
    return -1;
}
int main() {
    string a = "abcxabcdabxabcdabcdabcy";
    string b = "abcy";

    vector<int> next(b.length());
    getNext(b, next);
    
    cout << "next数组:" << endl;
    for (int i = 0; i < next.size(); i++) cout << next[i] << " ";

    int ans=KMP(a, b, next);
    cout << endl << "匹配到主串位置为:" << ans << endl;

    return 0;
}
posted @ 2020-10-07 00:06  肥斯大只仔  阅读(90)  评论(0编辑  收藏  举报