洛谷 P5410 【模板】擴展KMP

題目鏈接

https://www.luogu.org/problem/P5410

分析

國外一般稱此算法爲Z Algorithm,個人感覺算法思想上和Manacher算法更爲接近;

next[i]next[i] 表示模式串 SS 後綴 i...ni ... nSS 的最大公共前綴長度;

若已求 next[1...x1]next[1 ... x - 1],接下來要求 next[x]next[x]

記錄當前擴展最遠的點,即 max1k<x(k+next[k]1)max_{1 \leq k < x} (k + next[k] - 1)

nextnext 數組定義可知,S[1...next[k]]=S[k...k+next[k]1]S[1 ... next[k]] = S[k ... k + next[k] - 1]

S[1...next[xk+1]]=S[xk+1...xk+next[xk+1]]S[1 ... next[x - k + 1]] = S[x - k + 1 ... x - k + next[x - k + 1]]

S[xk+1...xk+next[xk+1]]=S[x...x+next[xk+1]1]S[x - k + 1 ... x - k + next[x - k + 1]] = S[x ... x + next[x - k + 1] - 1]

故有 S[1...next[xk+1]]=S[x...x+next[xk+1]1]S[1 ... next[x - k + 1]] = S[x ... x + next[x - k + 1] - 1]

x+next[xk+1]1x + next[x - k + 1] - 1 未到達擴展到的最遠位置,則 next[x]next[x] 便可確定;

否則,暴力先後擴展,並更新擴展到的最遠位置,

仿照KMP算法,利用 nextnext 數組求出原問題答案;

擴展到的最遠位置要麼增加,要麼不變,複雜度爲 O(n)O(n)

AC代碼

#include <cstdio>
#include <cstring>

const int maxn = 1e5 + 5;

int nxt[maxn], ex[maxn], l1, l2;
char a[maxn], b[maxn];

inline void get_nxt() {
	nxt[1] = l2;
	for (int i = 1; i < l2 && b[i] == b[i + 1]; ++i) ++nxt[2];
	int k = 2;
	for (int i = 3; i <= l2; ++i) {
		int p = k + nxt[k] - 1;
		if (i + nxt[i - k + 1] - 1 < p) nxt[i] = nxt[i - k + 1];
		else {
			int j = p - i + 1;
			if (j < 1) j = 1;
			while (i + j - 1 <= l2 && b[i + j - 1] == b[j]) ++j;
			nxt[i] = j - 1, k = i;
		}
	}
}

inline void exkmp() {
	get_nxt();
	for (int i = 1; i <= l1 && i <= l2; ++i) {
		if (a[i] != b[i]) break;
		++ex[1];
	}
	int k = 1;
	for (int i = 2; i <= l1; ++i) {
		int p = k + ex[k] - 1;
		if (i + nxt[i - k + 1] - 1 < p) ex[i] = nxt[i - k + 1];
		else {
			int j = p - i + 1;
			if (j < 1) j = 1;
			while (i + j - 1 <= l1 && j <= l2 && a[i + j - 1] == b[j]) ++j;
			ex[i] = j - 1, k = i;
		}
	}
}

int main() {
	scanf("%s%s", a + 1, b + 1);
	l1 = strlen(a + 1), l2 = strlen(b + 1);
	exkmp();
	for (int i = 1; i <= l2; ++i) printf("%d ", nxt[i]);
	puts("");
	for (int i = 1; i <= l1; ++i) printf("%d ", ex[i]);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章