exKMP
给出模板串A和子串B,长度分别为lenA和lenB,要求在线性时间内,对于每个Ai,求出A[i…lenA]与B的最长公共前缀长度
#include<bits/stdc++.h>
using namespace std;
char sa[1100000], sb[1100000];
int lena, lenb;
int p[1100000], ex[1100000];
//p数组是用来让B串自己匹配自己的
void exkmp()
{
p[1] = lenb;
int x = 1;
while (sb[x] == sb[x + 1] && x + 1 <= lenb) x++;//因为我们p[1]是具有一定性,所以我们不能直接用,所以要先暴力求出p[2]
p[2] = x - 1;
int k = 2;
for (int i = 3; i <= lenb; i++)
{
int pp = k + p[k] - 1, L = p[i - k + 1];//pp实际上是p
if (i + L < pp + 1) p[i] = L;//i-k+L<pp-k+1化简后i+L<pp
else
{
int j = pp - i + 1;
if (j < 0) j = 0;
while (sb[j + 1] == sb[i + j] && i + j <= lenb) j++;
p[i] = j;
k = i;
}
}
x = 1;
while (sa[x] == sb[x] && x <= lenb) x++;//ex[1]并不具有一定性,所以我们暴力求出ex[1]
ex[1] = x - 1;
k = 1;
for (int i = 2; i <= lena; i++)
{
int pp = k + ex[k] - 1, L = p[i - k + 1];
if (i + L < pp + 1) ex[i] = L;
else
{
int j = pp - i + 1;
if (j < 0) j = 0;
while (sb[j + 1] == sa[i + j] && i + j <= lena && j <= lenb) j++;
ex[i] = j;
k = i;
}
}
}
int main()
{
scanf("%s%s", sa + 1, sb + 1);
lena = strlen(sa + 1); lenb = strlen(sb + 1);
exkmp();
for (int i = 1; i < lena; i++) printf("%d ", ex[i]);
printf("%d\n", ex[lena]);
return 0;
}