扩展KMP算法模板
Description
\(txt\)为文本串,\(pat\)为模式串。
\(nxt[i]\): \(pat[i:]\)与\(pat[]\)的最长公共前缀的长度。
\(ext[i]\): \(txt[i:]\)与\(pat[]\)的最长公共前缀的长度。
\(pre\_kmp(pat)\):模式串与模式串自己匹配,得到\(nxt[]\)数组。
\(ext\_kmp(txt,pat)\):求\(nxt[]\)与\(pat[]\)数组。
Input
第一行给出文本串\(txt\),第二行给出模式串\(pat\)。
Output
输出\(ext[]\)数组。
Sample Input
abaabaab
aaba
Sample Output
1 0 4 1 0 3 1 0
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 1e3 + 10;
int nxt[N], ext[N];
void pre_kmp(char pat[])
{
int lpat = strlen(pat);
nxt[0] = lpat;
int j = 0;
while (j + 1 < lpat && pat[j] == pat[j + 1]) j++;
nxt[1] = j;
for (int i = 2, k = 1; i < lpat; i++)
{
int p = nxt[k] + k - 1;
int l = nxt[i - k];
if (i + l < p + 1) nxt[i] = l;
else
{
j = max(0, p - i + 1);
while (i + j < lpat && pat[i + j] == pat[j]) j++;
nxt[i] = j;
k = i;
}
}
}
void ext_kmp(char txt[], char pat[])
{
pre_kmp(pat);
int ltxt = strlen(txt);
int lpat = strlen(pat);
int j = 0;
while (j < ltxt && j < lpat && pat[j] == txt[j]) j++;
ext[0] = j;
for (int i = 1, k = 0; i < ltxt; i++)
{
int p = ext[k] + k - 1;
int l = nxt[i - k];
if (i + l < p + 1) ext[i] = l;
else
{
j = max(0, p - i + 1);
while (i + j < ltxt && j < lpat && txt[i + j] == pat[j]) j++;
ext[i] = j;
k = i;
}
}
}
char txt[N], pat[N];
int main()
{
scanf("%s%s", txt, pat);
ext_kmp(txt, pat);
int len = strlen(txt);
for (int i = 0; i < len; i++) printf("%d ", ext[i]);
return 0;
}