题目描述

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的更多相关文章

  1. [USACO06DEC] Milk Patterns

    题目描述 Farmer John has noticed that the quality of milk given by his cows varies from day to day. On f ...

  2. 解题:USACO06DEC Milk Patterns

    题面 初见SA 用了一个常见的按$height$分组的操作:二分答案,然后按$height$分组,遇到一个$height$小于$mid$的就丢进下一组并更新答案,如果最多的那组不少于$k$个说明可行 ...

  3. BZOJ 1717 [USACO06DEC] Milk Patterns (后缀数组+二分)

    题目大意:求可重叠的相同子串数量至少是K的子串最长长度 洛谷传送门 依然是后缀数组+二分,先用后缀数组处理出height 每次二分出一个长度x,然后去验证,在排序的后缀串集合里,有没有连续数量多于K个 ...

  4. luoguP2852 [USACO06DEC]Milk Patterns

    题意 显然如果有一个子串出现过\(k\)次,那么它必定是一个至少长为k的后缀序的\(LCP\),求出所有相邻的长为\(k-1\)的\(height\)数组的最小值,在其中取最大值即可 code: #i ...

  5. [洛谷P2852] [USACO06DEC]牛奶模式Milk Patterns

    洛谷题目链接:[USACO06DEC]牛奶模式Milk Patterns 题目描述 Farmer John has noticed that the quality of milk given by ...

  6. 【BZOJ-1717】Milk Patterns产奶的模式 后缀数组

    1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 881  Solved:  ...

  7. BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 [后缀数组]

    1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1017  Solved: ...

  8. POJ 3261 Milk Patterns 后缀数组求 一个串种 最长可重复子串重复至少k次

    Milk Patterns   Description Farmer John has noticed that the quality of milk given by his cows varie ...

  9. POJ 3261 Milk Patterns (求可重叠的k次最长重复子串)+后缀数组模板

    Milk Patterns Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 7586   Accepted: 3448 Cas ...

随机推荐

  1. AWS 推出长期支持的 OpenJDK 免费分发版本 —— Amazon Corretto

    简评:听说 Oracle JDK 要收费了,Oracle 要限制 Java 的商业或生产用途,针对这个问题,AWS 将会推出 Amazon Corretto. Java 是 AWS 用户使用的最流行的 ...

  2. leetcode-39-组合总和(有趣的递归)

    题目描述: 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的数字可以无 ...

  3. 集合之六:Map接口

    Map接口概述 Map接口中的集合和Collection接口中的集合在存储数据的格式上有很大的不同,Map接口下的内容是以<K , V> ,键值对的形式存储的,我们查询API,Map接口的 ...

  4. 基础概念——令人迷惑的EOF

    EOF概念常常使人迷惑. 首先我们要理解并没有像EOF字符这样的东西. 进一步讲EOF是由内核检测到的一种条件. 应用程序在它接收到由read函数返回的零返回码时,它就会发现EOF条件. 对于磁盘文件 ...

  5. 9. Javascript学习笔记——表单处理

    9. 表单处理 9.1 表单的基础知识 ///表单用 <form> 元素表示,对应的是 HTMLFormElement 类型,继承自 HTMLElement. //属性:action.me ...

  6. springcloud(五)-Ribbon

    前言 先发句牢骚,最近太TM忙了,一直没时间静下心来继续写微服务架构!EMMMMMM..... 经过前文的讲解,我们已经实现了微服务的注册与发现.启动各个微服务时,Eureka Client会把自己的 ...

  7. Cinderella

    Chapter 1 Ella, Ella, CinderellaThere is a beauiful girl. Her name is Ella.She lives with a wicked s ...

  8. 聊一聊Iterable与Iterator的那些事!

    前言 欢迎关注公众号:Coder编程 获取最新原创技术文章和相关免费学习资料,随时随地学习技术知识! 在上一篇文章通过面试题,让我们来了解Collection,我们会发现Collection接口之上还 ...

  9. Django获取Header中的信息

    今天需要从header中获取一些信息,查了一些资料,需要注意一下几点: request.META.get("header key") 用于获取header的信息 注意的是heade ...

  10. WPF INotifyPropertyChanged

    public class OrderModel:INotifyPropertyChanged { public string _oderID; public string OrderID; { get ...