洛谷题目链接:[USACO06DEC]牛奶模式Milk Patterns

题目描述

Farmer John has noticed that the quality of milk given by his cows varies from day to day. On further investigation, he discovered that although he can't predict the quality of milk from one day to the next, there are some regular patterns in the daily milk quality.

To perform a rigorous study, he has invented a complex classification scheme by which each milk sample is recorded as an integer between 0 and 1,000,000 inclusive, and has recorded data from a single cow over N (1 ≤ N ≤ 20,000) days. He wishes to find the longest pattern of samples which repeats identically at least K (2 ≤ K ≤ N) times. This may include overlapping patterns -- 1 2 3 2 3 2 3 1 repeats 2 3 2 3 twice, for example.

Help Farmer John by finding the longest repeating subsequence in the sequence of samples. It is guaranteed that at least one subsequence is repeated at least K times.

农夫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: Two space-separated integers: N and K

Lines 2..N+1: N integers, one per line, the quality of the milk on day i appears on the ith line.

输出格式:

Line 1: One integer, the length of the longest pattern which occurs at least K times

输入输出样例

输入样例#1:

8 2

1

2

3

2

3

2

3

1

输出样例#1:

4

题意: 找最少出现\(k\)次的子串的最大长度.

题解: 根据贪心策略,子串变长答案不会减小,所以可以看做是求\(k\)个后缀的\(LCP\).因为要求\(LCP\)的最大值,而\(LCP(suffix(sa[i]),suffix(sa[j]))=min\{height[k]\}(i<j,k\in[i,j])\),显然当这\(k\)个后缀在排名上连续的时候可以取得最小值.因为若排名不连续,那么涵盖的取最小值的范围一定会变大,而当取值范围变大最小值只会变小.所以这个贪心是正确的.

那么我们就直接后缀数组求出\(height\)数组,然后枚举排名一遍单调队列扫一下长度为\(k-1\)的滑动窗口中的最小值,并对这些最小值取个\(max\)就是答案了.

为什么滑动窗口的长度是\(k-1\)呢?因为\(height[i]=lcp(suffix(sa[i]),suffix(sa[i-1]))\),所以\(k-1\)个\(height\)就可以计算出\(k\)个后缀的\(LCP\)的最小值啦.

#include<bits/stdc++.h>
using namespace std;
const int N = 40000+5;
const int inf = 0x3f3f3f3f; int n, m, k, sa[N], rk[N], buk[N], sec[N], q[N], a[N], height[N], h, t, ans; void rsort(){
for(int i = 0; i <= m; i++) buk[i] = 0;
for(int i = 1; i <= n; i++) buk[rk[i]]++;
for(int i = 1; i <= m; i++) buk[i] += buk[i-1];
for(int i = n; i >= 1; i--) sa[buk[rk[sec[i]]]--] = sec[i];
} void SuffixArray(){
for(int i = 1; i <= n; i++) rk[i] = a[i], sec[i] = i;
m = n; rsort(); int num = 0;
for(int l = 1; l <= n && num < n; l <<= 1){
num = 0;
for(int i = 1; i <= l; i++) sec[++num] = n-l+i;
for(int i = 1; i <= n; i++) if(sa[i] > l) sec[++num] = sa[i]-l;
rsort(); swap(sec, rk); rk[sa[1]] = num = 1;
for(int i = 2; i <= n; i++)
rk[sa[i]] = (sec[sa[i]] == sec[sa[i-1]] && sec[sa[i]+l] == sec[sa[i-1]+l]) ? num : ++num;
m = num;
}
} void get_height(){
int j, k = 0;
for(int i = 1; i <= n; i++){
if(k) k--;
j = sa[rk[i]-1];
while(a[i+k] == a[j+k]) k++;
height[rk[i]] = k;
}
} int main(){
ios::sync_with_stdio(false);
cin >> n >> k;
for(int i = 1; i <= n; i++) cin >> a[i];
SuffixArray(), get_height();
h = 1, t = 0;
for(int i = 1; i <= n; i++){ // i for ranks
while(h <= t && height[i] <= height[q[t]]) t--;
q[++t] = i;
while(h <= t && q[t]-q[h]+1 > k-1) h++;
ans = max(ans, height[q[h]]);
}
cout << ans << endl;
return 0;
}

[洛谷P2852] [USACO06DEC]牛奶模式Milk Patterns的更多相关文章

  1. luogu P2852 [USACO06DEC]牛奶模式Milk Patterns 后缀数组 + Height数组 + 二分答案 + 扫描

    后缀数组有一个十分有趣的性质: $height[rk[i]] >= height[rk[i-1]] - 1$    Code: #include <bits/stdc++.h> #d ...

  2. Luogu P2852 [USACO06DEC]牛奶模式Milk Patterns

    题目链接 \(Click\) \(Here\) 水题.利用\(Height\)的性质维护一个单调栈即可. #include <bits/stdc++.h> using namespace ...

  3. P2852 [USACO06DEC]牛奶模式Milk Patterns

    link 这是一道后缀匹配的模板题 我们只需要将height算出来 然后二分一下答案就可以了 #include<cstdio> #include<algorithm> #inc ...

  4. 【后缀数组】【LuoguP2852】 [USACO06DEC]牛奶模式Milk Patterns

    题目链接 题目描述 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠.我们称之为一个"模式". J ...

  5. [Luogu2852][USACO06DEC]牛奶模式Milk Patterns

    Luogu 一句话题意 给出一个串,求至少出现了\(K\)次的子串的最长长度. sol 对这个串求后缀数组. 二分最长长度. 如果有\(K\)个不同后缀他们两两的\(lcp\)都\(>=mid\ ...

  6. [USACO06DEC] 牛奶模式Milk Patterns

    题目链接:戳我 我们知道后缀数组的h数组记录的是后缀i和后缀i-1的最长公共前缀长度,后缀的前缀其实就是子串. 因为是可以重复出现的子串,所以我们只要计算哪些h数组的长度大于等于x即可.这一步操作我们 ...

  7. 洛谷P2852 牛奶模式Milk Patterns [USACO06DEC] 字符串

    正解:SA/二分+哈希 解题报告: 传送门! umm像这种子串的问题已经算是比较套路的了,,,?就后缀的公共前缀这样儿的嘛QwQ 所以可以先求个SA 然后现在考虑怎么判断一个长度为d的子串出现了k次? ...

  8. 洛谷P3093 [USACO13DEC]牛奶调度Milk Scheduling

    题目描述 Farmer John has N cows that need to be milked (1 <= N <= 10,000), each of which takes onl ...

  9. 2018.07.17 牛奶模式Milk Patterns(二分+hash)

    传送门 一道简单的字符串.这里收集了几种经典做法: SAM,不想写. 后缀数组+二分,不想写 后缀数组+单调队列,不想写 hash+二分,for循哈希,天下无敌!于是妥妥的hash 代码如下: #in ...

随机推荐

  1. nginx配置和网站的部署

    环境: CentOS Linux release 7.3.1611 (Core) nginx version: nginx/1.13.4 PHP 5.4.16 (cli) (built: Nov 6 ...

  2. Qt窗口及控件-QTreeview/QTableView排序问题

    版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:Qt-QTreeview/QTableView排序问题     本文地址:http://tec ...

  3. c++ new 堆 栈

    根据32位的Windows系统默认有2GB的用户空间,则不能new超过2GB的,执行下列代码: ***]; 会出现下面的错误 error C2148: 数组的总大小不得超过 0x7fffffff 字节 ...

  4. 在html在添加cookie和读取cookie

    1.保存cookie var oDate = new Date(); oDate.setDate(oDate.getDate() + );//有效期为30天 document.cookie = &qu ...

  5. 【Python】Python 过滤列表

    如你所知,Python 具有通过列表解析将列表映射到其它列表的强大能力.这种能力同过滤机制结合使用,使列表中的有些元素被映射的同时跳过另外一些元素.过滤列表语法: [mapping-expressio ...

  6. Python替换字符串中的反斜杠\

    s = 'cdp\nd' result = eval(repr(s).replace('\\', '@')) print(result) repr() 函数可以将字符串转换为python的原始字符串( ...

  7. 消息传递 树形DP

    非常妙的树形DP:由于n很小,我们可以枚举每一个点作为第一个节点,计算其时间花费 那么问题就转化为对于给点节点求花费时间. 通过观察,显然我们会发现先传给花费时间多的人更加合算,因为这样可以最大限度的 ...

  8. POJ3347:Kadj Squares——题解

    http://poj.org/problem?id=3347 题目大意:给定一些正方形的边长,让他们尽可能向左以45°角排列(不能互相重合),求在上面看只能看到哪几个正方形. ———————————— ...

  9. POJ3678:Katu Puzzle——题解

    http://poj.org/problem?id=3678 总觉得这题比例题简单. 设a为x取0的点,a+n为x取1的点. 我们还是定义a到b表示取a必须取b. 那么我们有: 当AND: 1.当c= ...

  10. BZOJ1604 & 洛谷2906:[USACO2008 OPEN]Cow Neighborhoods 奶牛的邻居——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1604 https://www.luogu.org/problemnew/show/P2906#sub ...