RT,用Z算法解border数组。方法是对于每个 i,将 bord[i+zi−1] 赋值为 zi,然后从后往前倒推(bord[i] = max(bord[i], bord[i + 1])
)洛谷数据都过了,请问这个算法是否正确?
code:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
const int N = 1000000;
char a[N + 10], b[N + N + 10];
int z[N + N + 10];
void get_z(const char *str, const int len, int *arr) {
int maxl = 0, maxr = 0;
// [1, maxr - maxl + 1] = [maxl, maxr]
// [i - maxl + 1, maxr - maxl + 1] = [i, maxr]
arr[1] = len;
for (int i = 2; i <= len; ++ i) {
if (i <= maxr) {
arr[i] = std::min(arr[i - maxl + 1], maxr - i + 1);
}
while (i + arr[i] <= len && str[arr[i] + 1] == str[i + arr[i]])
++ arr[i];
if (i + arr[i] - 1 > maxr) {
maxr = i + arr[i] - 1;
maxl = i;
}
}
return;
}
int n, m;
int bord[N + 10];
int main() {
scanf("%s%s", a + 1, b + 1);
n = strlen(a + 1);
m = strlen(b + 1);
get_z(b, m, z);
// for (int i = 1; i <= m; ++ i) {
// printf("z[%d]=%d\n", i, z[i]);
// }
for (int i = m; i >= 2; -- i) {
bord[i + z[i] - 1] = z[i];
}
for (int i = m - 1; i >= 1; -- i) {
bord[i] = std::max(bord[i], bord[i + 1] - 1);
}
b[m + 1] = '#';
for (int i = 1; i <= n; ++ i) {
b[m + 1 + i] = a[i];
}
get_z(b, m + 1 + n, z);
for (int i = 1; i <= n; ++ i) {
if (z[m + 1 + i] == m)
printf("%d\n", i);
}
for (int i = 1; i <= m; ++ i) {
printf("%d ", bord[i]);
}
printf("\n");
return 0;
}