1. 程式人生 > >HihoCoder - 1403 後綴數組一·重復旋律

HihoCoder - 1403 後綴數組一·重復旋律

hihocode ans -c names eof cpp highlight printf pri

描述

小Hi平時的一大興趣愛好就是演奏鋼琴。我們知道一個音樂旋律被表示為長度為 N 的數構成的數列。

小Hi在練習過很多曲子以後發現很多作品自身包含一樣的旋律。旋律是一段連續的數列,相似的旋律在原數列可重疊。比如在1 2 3 2 3 2 1 中 2 3 2 出現了兩次。

小Hi想知道一段旋律中出現次數至少為K次的旋律最長是多少?

輸入

第一行兩個整數 N和K。1≤N≤20000 1≤K≤N

接下來有 N 個整數,表示每個音的數字。1≤數字≤100

輸出

一行一個整數,表示答案。

Sample Input

8 2
1
2
3
2
3
2
3
1

Sample Output

4

總結:打算把後綴數組復習一遍
本題很明顯求的是連續k個height數組的最小值當中的最大值,

然後有兩種做法二分或單調隊列
這裏用的是單調隊列
#include <bits/stdc++.h>

using namespace std;
const int maxn = 200005;
int n, K, rk[maxn], sa[maxn], y[maxn], ln, p, m, c[maxn];
int H[maxn], wr[maxn], q[maxn], l, r, a[maxn], pos[maxn], k;

bool cmp(int k1, int k2, int ls) {
	return wr[k1] == wr[k2] && wr[k1 + ls] == wr[k2 + ls];
}
void SA(int x) {
	m = x;
	for (int i = 1; i <= n; ++i) c[rk[i]]++;
	for (int i = 1; i <= m; ++i) c[i] += c[i - 1];
	for (int i = n; i >= 1; --i) sa[c[rk[i]]--] = i;
	ln = 1, p = 0;
	while(p < n) {
		k = 0;
		for (int i = n - ln + 1; i <= n; ++i) y[++k] = i;
		for (int i = 1; i <= n; ++i) if(sa[i] > ln) y[++k] = sa[i] - ln;
		memset(c, 0, sizeof c);
		for (int i = 1; i <= n; ++i) wr[i] = rk[i];
		for (int i = 1; i <= n; ++i) c[wr[y[i]]]++; 
		for (int i = 1; i <= m; ++i) c[i] += c[i - 1];
		for (int i = n; i >= 1; --i) sa[c[wr[y[i]]]--] = y[i];
		for (int i = 1; i <= n; ++i) wr[i] = rk[i];
		rk[sa[1]] = 1; p = 1;
		for (int i = 2; i <= n; ++i) {
			if(!cmp(sa[i], sa[i - 1], ln)) ++p;
			rk[sa[i]] = p;
		} 
	} ln <<= 1; m = p;
}
void Gh() {
	k = 0;
	for (int i = 1; i <= n; ++i) rk[sa[i]] = i;
	for (int i = 1; i <= n; ++i) {
		if(k) --k; int j = sa[rk[i] - 1];
		while(a[i + k] == a[j + k]) ++k;
		H[rk[i]] = k;
	}
}
int main() {
	scanf("%d%d", &n, &K);
	for (int i = 1; i <= n; ++i) scanf("%d", &rk[i]), a[i] = rk[i];
	SA(105); Gh(); int ans = 0;
	for (int i = 1; i <= n; ++i) {
		while(l < r && H[i] < q[r]) r--;
		q[++r] = H[i]; pos[r] = i;
		while(l < r && pos[l] <= i - K + 1) ++l;
		if(i >= K) ans = max(ans, q[l]);
	} printf("%d\n", ans); 
	for (int i = 1; i <= n; ++i) cout << H[i] << " ";
	return 0;
}

  

 

HihoCoder - 1403 後綴數組一·重復旋律