求解算法正确性
查看原帖
求解算法正确性
107880
枫初音斗颂皮楼主2020/12/14 14:47

RT,用Z算法解border数组。方法是对于每个 ii,将 bord[i+zi1]bord[i+z_i-1] 赋值为 ziz_i,然后从后往前倒推(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;
}
2020/12/14 14:47
加载中...