KMP 模板

问题

a : abbaabbaaba
b : abbaaba
求字符串a中一共有几个b字符串

思路
  • 复杂度(O n * m)常规的思路是从a的第一位开始和b进行比较,如果碰到一个字母不同,说明从a的第一个开始不能成功匹配。于是就从a的第二个字母与b相比较。
  • 复杂度(O n * m)在方法一的基础上,发现一个字母不匹配的话,如果a不回到第二个开始的话,这样复杂的降了很多。
    如果a不回退,b就要回退。而且b回退的越少越好。
    就例子而言:
    a : abbaabbaaba
    b : abbaaba
    (下标从0开始)
    当匹配到最后一个字母发现不同(a[6] != b[6] 即 b != a),这时候让a[6]和b[2]开始匹配。完美!
    问题是你怎么知道是b[2]呢?这涉及到字符串的前后缀问题,也就是求解next数组

求next数组

//不懂的可以 手动模拟 || 百度 || 记住
Next[0] = -1;    
int i = 0, j = -1;
while (i < m) { //m 表示数组或字符串的长度
    if(j == -1 || b[i] == b[j]) {
        Next[++i] = ++j;    //赋值 
    }else {
        j = Next[j];    //回溯 
    }
}

KMP模板

int a[N], b[N], Next[N];    //从a数组里匹配b数组
void get_next(int m) {  //求Next数组 
    Next[0] = -1;    
    int i = 0, j = -1;
    while (i < m) {
        if(j == -1 || b[i] == b[j]) {
            Next[++i] = ++j;    //赋值 
        }else {
            j = Next[j];    //回溯 
        }
    }
}
int kmp(int n, int m) {
    get_next(m);    //求Next数组 
    int i = 0, j = 0;
    int ans = 0;
    while (i < n) {
        if (j == -1 || a[i] == b[j]) {  //当前匹配成功进行下一个匹配 
            i++;
            j++;    
        }else {
            j = Next[j];
        }
        if (j == m) {   //匹配成功 
            ans++;
            j = Next[j];    //进行下一次匹配 
        }
    }
    return ans;
}

猜你喜欢

转载自blog.csdn.net/henuyh/article/details/80216733
今日推荐