字符串算法总结——扩展KMP算法

扩展KMP算法

功能:处理字符串 S 的所有后缀与字符串 T 的最长公共前缀。

需要的数组
1.Next数组
next[i] 表示后缀 i 即 Ti⋯∣T∣​ 与 T 的最长公共前缀。
例如

数组索引          1   2   3   4   5   6   7   8   9
字符串数组     a   a   a   b   a   a   a   a   b
next数组        9   2   1   0   3   4   2   1   0

如何求Next呢,我也不知道,背下来模板即可

void getnext() {
    next[1] = n;
    int p = 1;
    while(p < n && t[p] == t[p + 1]) p++;
    next[2] = p-1;
    int k = 2,l;
    for(int i = 3; i <= n; i++) {
        p = k + next[k] - 1;
        l = next[i - k + 1];
        if (i + l <= p) next[i] = l;
        else {
            int j = p - i + 1;
            if(j < 0)     j = 0;
            while(i + j <= n && t[i + j] == t[j + 1])     j++;
            next[i] = j;
            k = i;
        }
    }
}

2.Exnext[]数组,这个数组就是答案啦,直接给出代码

void getextend() {
    int p = 0;
    while (p < m && p < n && s[p + 1] == t[p + 1]) {
        p++;
    }
    extend[1] = p;
    int k = 1, l;
    for (int i = 2; i <= m; i++) {
        p = k + extend[k] - 1;
        l = next[i - k + 1];
        if (i + l <= p) {
            extend[i] = l;
        } else {
            int j = p - i + 1;
            if(j < 0) j = 0;
            while(i + j <= m && j + 1 <=n && s[i + j] == t[j + 1])    j ++;
            extend[i] = j;
            k = i;
        }
    }
}

这里同样给出两组EXKMP模板,个人喜欢第一个

第一个模板

void getnext() {
    next[1] = n;
    int p = 1;
    while(p < n && t[p] == t[p + 1]) p++;
    next[2] = p-1;
    int k = 2,l;
    for(int i = 3; i <= n; i++) {
        p = k + next[k] - 1;
        l = next[i - k + 1];
        if (i + l <= p) next[i] = l;
        else {
            int j = p - i + 1;
            if(j < 0)     j = 0;
            while(i + j <= n && t[i + j] == t[j + 1])     j++;
            next[i] = j;
            k = i;
        }
    }
}

void getextend() {
    int p = 0;
    while (p < m && p < n && s[p + 1] == t[p + 1]) {
        p++;
    }
    extend[1] = p;
    int k = 1, l;
    for (int i = 2; i <= m; i++) {
        p = k + extend[k] - 1;
        l = next[i - k + 1];
        if (i + l <= p) {
            extend[i] = l;
        } else {
            int j = p - i + 1;
            if(j < 0) j = 0;
            while(i + j <= m && j + 1 <=n && s[i + j] == t[j + 1])    j ++;
            extend[i] = j;
            k = i;
        }
    }
}

第二个

#include <iostream>
#include <string.h>
using namespace std;
const int maxn=1100;
int Next[maxn],extend[maxn];

void get_Next(char *s) {
    int n = strlen(s);
    int i, j, k;
    for(j = 0; 1 + j < n && s[j] == s[1 + j]; ++j);
    Next[1] = j;
    k = 1;
    for(i = 2; i < n; ++i) {
        int len = k + Next[k], L = Next[i - k];
        if (L < len - i) {
            Next[i] = L;
        } else {
            for (j = max(0, len - i); i + j < n && s[j] == s[i + j]; ++j);
            Next[i] = j;
            k = i;
        }
    }
    Next[0] = n;
}

void ex_kmp(char *T, char *s) {
    int n = strlen(T), m = strlen(s);
    int i, j, k;
    for(j = 0; j < n && j < m && T[j] == s[j]; ++j);
    extend[0] = j;
    k = 0;
    for (i = 1; i < n; ++i) {
        int len = k + extend[k], L = Next[i - k];
        if(L < len-i) {
            extend[i] = L;
        } else {
            for (j = max(0, len - i); j < m && i + j < n && s[j] == T[i + j]; ++j);
            extend[i] = j;
            k = i;
        }
    }
}

int main() {
    char s[maxn],T[maxn];
    cin>>T>>s;
    get_Next(s);
ex_kmp(T, s);
for (int i = 0; i < strlen(T); ++i) {
    cout << extend[i] << " ";
}
    cout << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/liukairui/article/details/80633232
今日推荐