[BZOJ1717][Usaco2006 Dec]Milk Patterns 产奶的模式

[BZOJ1717][Usaco2006 Dec]Milk Patterns 产奶的模式

试题描述

农夫John发现他的奶牛产奶的质量一直在变动。经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠。我们称之为一个“模式”。 John的牛奶按质量可以被赋予一个0到1000000之间的数。并且John记录了N(1<=N<=20000)天的牛奶质量值。他想知道最长的出现了至少K(2<=K<=N)次的模式的长度。比如1 2 3 2 3 2 3 1 中 2 3 2 3出现了两次。当K=2时,这个长度为4。

输入

* Line 1: 两个整数 N,K。

* Lines 2..N+1: 每行一个整数表示当天的质量值。

输出

* Line 1: 一个整数:N天中最长的出现了至少K次的模式的长度

输入示例

8 2
1
2
3
2
3
2
3
1

输出示例

4

数据规模及约定

见“试题描述

题解

求出后缀数组然后用一个长度为 K - 1 的区间扫一遍 height 数组。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;

int read() {
	int x = 0, f = 1; char c = getchar();
	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
	return x * f;
}

#define maxn 20010
#define maxlog 15

int n, S[maxn], num[maxn];

int rank[maxn], height[maxn], sa[maxn], Ws[maxn];
bool cmp(int* a, int p1, int p2, int l) {
	if(p1 + l > n && p2 + l > n) return a[p1] == a[p2];
	if(p1 + l > n || p2 + l > n) return 0;
	return a[p1] == a[p2] && a[p1+l] == a[p2+l];
}
void ssort() {
	int *x = rank, *y = height;
	int m = 0;
	for(int i = 1; i <= n; i++) Ws[x[i] = S[i]]++, m = max(m, x[i]);
	for(int i = 1; i <= m; i++) Ws[i] += Ws[i-1];
	for(int i = n; i; i--) sa[Ws[x[i]]--] = i;
	for(int j = 1, pos; pos < n; j <<= 1, m = pos) {
		pos = 0;
		for(int i = n - j + 1; i <= n; i++) y[++pos] = i;
		for(int i = 1; i <= n; i++) if(sa[i] > j) y[++pos] = sa[i] - j;
		for(int i = 1; i <= m; i++) Ws[i] = 0;
		for(int i = 1; i <= n; i++) Ws[x[i]]++;
		for(int i = 1; i <= m; i++) Ws[i] += Ws[i-1];
		for(int i = n; i; i--) sa[Ws[x[y[i]]]--] = y[i];
		swap(x, y); pos = 1; x[sa[1]] = 1;
		for(int i = 2; i <= n; i++) x[sa[i]] = cmp(y, sa[i], sa[i-1], j) ? pos : ++pos;
	}
	return ;
}
void calch() {
	for(int i = 1; i <= n; i++) rank[sa[i]] = i;
	for(int i = 1, j, k = 0; i <= n; height[rank[i++]] = k)
		for(k ? k-- : 0, j = sa[rank[i]-1]; S[j+k] == S[i+k]; k++) ;
	return ;
}

int lcp[maxlog][maxn], Log[maxn];
void rmq_init() {
	Log[1] = 0;
	for(int i = 2; i <= n; i++) Log[i] = Log[i>>1] + 1;
	for(int i = 1; i <= n; i++) lcp[0][i] = height[i];
	for(int j = 1; (1 << j) <= n; j++)
		for(int i = 1; i + (1 << j) - 1 <= n; i++)
			lcp[j][i] = min(lcp[j-1][i], lcp[j-1][i+(1<<j-1)]);
	return ;
}
int query(int ql, int qr) {
	int len = qr - ql + 1, t = Log[len];
	return min(lcp[t][ql], lcp[t][qr-(1<<t)+1]);
}

int main() {
	n = read(); int K = read();
	for(int i = 1; i <= n; i++) num[i] = S[i] = read();
	
	sort(num + 1, num + n + 1);
	for(int i = 1; i <= n; i++) S[i] = lower_bound(num + 1, num + n + 1, S[i]) - num;
	ssort();
	calch();
	rmq_init();
	
	int ans = 0;
	for(int ql = 1; ql <= n - K + 1; ql++) {
		int qr = ql + K - 1;
		ans = max(ans, query(ql + 1, qr));
	}
	printf("%d
", ans);
	
	return 0;
}
原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6491283.html