zoukankan      html  css  js  c++  java
  • [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;
    }
    
  • 相关阅读:
    Spring容器基础ClassPathXmlApplicationContext(一起看源码)
    Spring容器基础xmlbeanfactory(一起看源码)
    java类库字符串操作
    反射
    maven配置文件解析
    红帽(Red Hat Linux)下SVN服务器的安装与配置
    Ant构建与部署Java项目---入门
    输入两个链表,找出他们的第一个公共节点
    java实现双向链表
    java实现双端链表
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6491283.html
Copyright © 2011-2022 走看看