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 ...
随机推荐
- 在Myeclipse中查看android源码就是这么easy
在开发android 时不能查看源码必是很不爽的一件事,看过网上一些文章后(都是2.0以前的版本,跟我的2.2最新版本的配置是不一样的)不过还是给了我启示,通过配置终于可以在myeclipse中查看源 ...
- Memcached安装教程及使用
Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载 Table of contents 安装 使用 在spring中使用 安装 下载下来m ...
- JSP常用Form表单控件
[easyui]--combobox--赋值和获取选中的值 /初始化下拉选框 $('#communityIdDiv').combobox({ url:basepath+"pushContro ...
- spring cloud ribbon源码解析(一)
我们知道spring cloud中restTemplate可以通过服务名调接口,加入@loadBalanced标签就实现了负载均衡的功能,那么spring cloud内部是如何实现的呢? 通过@loa ...
- 递归实现快速幂(C++版)
快速幂是什么? 顾名思义,快速幂就是快速算底数的n次幂.其时间复杂度为 O(log₂N), 与朴素的O(N)相比效率有了极大的提高. 就以a的b次方来介绍: 把b转换成二进制数,该二进制数第i位的权为 ...
- H01-Linux系统中搭建Hadoop和Spark集群
前言 1.操作系统:Centos7 2.安装时使用的是root用户.也可以用其他非root用户,非root的话要注意操作时的权限问题. 3.安装的Hadoop版本是2.6.5,Spark版本是2.2. ...
- 基于CentOS7系统一键配置Aria2 实现服务器离线下载工具
我们有些网友购买的海外VPS主机并不是用来做网站的,而是用来作为下载资源工具使用的.确实用这样的工具搭建之后是比本地下载速度快,因为有些资源.软件等是海外资源,而且挂载在服务器上不占用本地的资源.在这 ...
- 基于聚类的“图像分割”(python)
基于聚类的“图像分割” 参考网站: https://zhuanlan.zhihu.com/p/27365576 昨天萌新使用的是PIL这个库,今天发现机器学习也可以这样玩. 视频地址Python机器学 ...
- (转)MySQL自带的性能压力测试工具mysqlslap详解
mysqlslap 是 Mysql 自带的压力测试工具,可以模拟出大量客户端同时操作数据库的情况,通过结果信息来了解数据库的性能状况 mysqlslap 的一个主要工作场景就是对数据库服务器做基准测试 ...
- Dubbo源码解读
1.提升SOA的微服务架构设计能力 通过读dubbo源码是一条非常不错的通往SOA架构设计之路,毕竟SOA的服务治理就是dubbo首先提出来的,比起你去看市面上的SOA微服务架构的书籍,学到的架构 ...