扩展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;
}