USACO06DEC Milk Patterns——Solution
题目描述
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。
--by luogu
https://daniu.luogu.org/problem/show?pid=2852
后缀数组查询可重叠出现超过k次的最长子串长度;
可以等价于height数组中所有长度为k-1的区间最小值的最大值;
不严谨的证明:
合法性:
某区间最小值即为该区间和其左端点减一所有子串的公共前缀;
于是她的确出现的k次,是合法的答案;
最优性:
设子串 x为最优答案;
她满足作为k+个后缀的前缀;
则这k+个后缀rank连续,即她们中第一个除外的height可构成一个长度大于等于k-1的区间;
而这个区间会把x贡献到答案上(否则意味着该区间min不是x——与“作为这k+个后缀的前缀”的条件矛盾)
于是得到结论:可以等价于height数组中所有长度为k-1的区间最小值的最大值;
于是可以使用O(n)的单调队列;
然而为什么在luogu的数据下O(nlogn)的二分len的方法并不慢于单调队列?
值得一提的,由于某(shu)些(ju)原(tai)因(shui)本来可能很大的

其实很小,(20多?30多?)......
代码如下:
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=;
int n,m=,k;
int x[MAXN],y[MAXN],c[MAXN],s[MAXN];
int sa[MAXN],rank[MAXN],height[MAXN];
int que[],h,t;
inline void build_sa();
inline void build_height();
inline void in(int &ans)
{
ans=;bool p=false;char ch=getchar();
while((ch>'' || ch<'')&&ch!='-') ch=getchar();
if(ch=='-') p=true,ch=getchar();
while(ch<=''&&ch>='') ans=ans*+ch-'',ch=getchar();
if(p) ans=-ans;
}
int main()
{
int i,j,k,ans=;
in(n),in(k);
for(i=;i<n;i++)
in(s[i]);
build_sa();
build_height();
h=,t=;
for(i=;i<n;i++){
while(h<t&&height[que[t]]>height[i])t--;
que[++t]=i;
if(i>=k-){
if(height[que[h+]]>ans)ans=height[que[h+]];
if(que[h+]<=i-k+)h++;
}
}
printf("%d",ans);
return ;
}
inline void build_sa(){
int i,j,k;
for(i=;i<=m;i++)c[i]=;
for(i=;i<n;i++)c[x[i]=s[i]]++;
for(i=;i<=m;i++)c[i]+=c[i-];
for(i=n-;i>=;i--)sa[--c[x[i]]]=i;
for(k=;k<=n;k<<=){
int num=;
for(i=n-k;i<n;i++)y[num++]=i;
for(i=;i<n;i++)if(sa[i]>=k)y[num++]=sa[i]-k;
for(i=;i<=m;i++)c[i]=;
for(i=;i<n;i++)c[x[i]]++;
for(i=;i<=m;i++)c[i]+=c[i-];
for(i=n-;i>=;i--)sa[--c[x[y[i]]]]=y[i],y[i]=;
swap(x,y);
num=;x[sa[]]=;
for(i=;i<n;i++)
if(y[sa[i]]!=y[sa[i-]]||y[sa[i]+k]!=y[sa[i-]+k])
x[sa[i]]=++num;
else
x[sa[i]]=num;
if(num>n)break;
m=num;
}
}
inline void build_height(){
int i,j,k=;
for(i=;i<n;i++)rank[sa[i]]=i;
for(i=;i<n;i++){
if(!rank[i])continue;
if(k)k--;
j=sa[rank[i]-];
while(j+k<n&&i+k<n&&s[i+k]==s[j+k])k++;
height[rank[i]]=k;
}
}
祝AC
USACO06DEC Milk Patterns——Solution的更多相关文章
- [USACO06DEC] Milk Patterns
题目描述 Farmer John has noticed that the quality of milk given by his cows varies from day to day. On f ...
- 解题:USACO06DEC Milk Patterns
题面 初见SA 用了一个常见的按$height$分组的操作:二分答案,然后按$height$分组,遇到一个$height$小于$mid$的就丢进下一组并更新答案,如果最多的那组不少于$k$个说明可行 ...
- BZOJ 1717 [USACO06DEC] Milk Patterns (后缀数组+二分)
题目大意:求可重叠的相同子串数量至少是K的子串最长长度 洛谷传送门 依然是后缀数组+二分,先用后缀数组处理出height 每次二分出一个长度x,然后去验证,在排序的后缀串集合里,有没有连续数量多于K个 ...
- luoguP2852 [USACO06DEC]Milk Patterns
题意 显然如果有一个子串出现过\(k\)次,那么它必定是一个至少长为k的后缀序的\(LCP\),求出所有相邻的长为\(k-1\)的\(height\)数组的最小值,在其中取最大值即可 code: #i ...
- [洛谷P2852] [USACO06DEC]牛奶模式Milk Patterns
洛谷题目链接:[USACO06DEC]牛奶模式Milk Patterns 题目描述 Farmer John has noticed that the quality of milk given by ...
- 【BZOJ-1717】Milk Patterns产奶的模式 后缀数组
1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 881 Solved: ...
- BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 [后缀数组]
1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1017 Solved: ...
- POJ 3261 Milk Patterns 后缀数组求 一个串种 最长可重复子串重复至少k次
Milk Patterns Description Farmer John has noticed that the quality of milk given by his cows varie ...
- POJ 3261 Milk Patterns (求可重叠的k次最长重复子串)+后缀数组模板
Milk Patterns Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 7586 Accepted: 3448 Cas ...
随机推荐
- LLDB 和Chisel 使用例子
打印变量 打印数字 (lldb) p/d 16 16 16 进制格式 (lldb) p/x 16 0x10 2 进制格式 (lldb) p/t 16 0b00000000000000000000000 ...
- 我把阿里云centos gcc从4.4.7升级到4.8.2的经历
我有试着去手动编译安装gcc,可是make的速度实在太慢,最后还直接失败了. 最后在csdn找到了个博客,说是使用yum来安装,网址为: http://blog.csdn.net/ppdouble/a ...
- Protocol Buffers介绍及例子
Protocol Buffers介绍及例子 Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化.它很适合做数据存储或数据交换格式.可用于通讯协 ...
- CSS03--框模型、定位position、浮动
我们接着“CSS02”,继续学习一些新的样式属性. 1.框模型: 规定了元素框处理 元素内容.内边距(padding).边框(border).外边距(margin,可以是负值)的方式 2.内边距 ...
- Groovy 反序列化漏洞分析(CVE-2015-3253)
0x00 前言 Java反序列化的漏洞爆发很久了,此前一直想学习一下.无奈Java体系太过于复杂,单是了解就花了我很久的时间,再加上懒,就一直拖着,今天恰好有空,参考@iswin大佬两年前的分析, ...
- Monkey and Banana
Monkey and BananaTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- 内核诊断(1)interrupt took too long
The linux kernel gathers samples using 'perf' performance monitor without affecting the latencies. T ...
- c# 操作excle
添加引用 Microsoft.Office.Interop.Excel; 添加命名空间 using Excel = Microsoft.Office.Interop.Excel; //创建接口变量- ...
- 在linux上安装 sql server for linux
在linux上安装 sql server for linux Install SQL Server on Red Hat Enterprise Linux Install SQL Server To ...
- html转图片,java库cssbox
引入依赖包 <dependency> <groupId>net.sf.cssbox</groupId> <artifactId>cssbox</a ...