KMP模板

网上其他人的博客写的都非常棒,我自己也只是有点明白,就放个模板吧。。。
从1开始存的字符串
假设要从B串中找好多个A串
想理解kmp就得明确数组的定义:nxt[i]表示A串中以i结尾的非前缀子串 与 A的前缀子串 能够匹配的最大长度
下面的代码为什么是j+1,不模拟一遍根本无法理解
我个人认为,j = nxt[j]是回到了上次匹配位置,你需要看j+1是否和i匹配,才能拓展j,更新nxt[i]

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
#define debug(x) cerr << #x << "=" << x << endl;
const int MAXN = 1000000 + 10;
const int INF = 1 << 30;
typedef long long ll;
int n,m,ans[MAXN],nxt[MAXN],tot;
char s1[MAXN], s2[MAXN];
void init_nxt(char *s) {
    nxt[1] = 0;
    for(int i=2, j=0; i<=m; i++) {
        while(j > 0 && s[i] != s[j+1]) j = nxt[j];
        if(s[i] == s[j+1]) j++;
        nxt[i] = j;
    }
}

void kmp(char *s, char *t) {
    for(int i=1, j=0; i<=n; i++) {
        while(j > 0 && s[i] != t[j+1]) j = nxt[j];
        if(s[i] == t[j+1]) j++;
        if(j == m) ans[++tot] = i - m + 1, j = nxt[j];
    }
}

int main() {
    cin >> s1 + 1 >> s2 + 1;
    n = strlen(s1+1), m = strlen(s2+1);
    init_nxt(s2);
    kmp(s1, s2);
    for(int i=1; i<=tot; i++) {
        printf("%d\n", ans[i]);
    }
    for(int i=1; i<=m; i++) {
        printf("%d ", nxt[i]);
    }
    return 0;
}
posted @ 2018-10-26 17:11  Zolrk  阅读(111)  评论(0编辑  收藏  举报