【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
题解
后缀数组+离散化
题目中m比较大,需要离散化。
对于这类求重复字串长度的问题,正着做比较难做。
我们可以先二分答案,然后将问题转化为是否有k次重复的字串。
假设有k次重复的字串,则一定有连续的k个height大于等于mid。
那么我们就可以在O(n)的时间内进行judge操作,总时间复杂度为O(nlogn),可以通过。
另:这里的judge写法比较特殊。由于height[n]是没有值的,所以一般情况下一定能进行下一步判断。但如果m=0,无论如何也无法进行,所以加上特判。
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 20005
int ws[N] , wv[N] , wa[N] , wb[N] , sa[N] , r[N] , n , m , k;
int rank[N] , height[N];
struct data
{
int num , rn , tnum;
}a[20001];
bool cmp1(data a , data b)
{
return a.num < b.num;
}
bool cmp2(data a , data b)
{
return a.rn < b.rn;
}
void da()
{
int i , j , p , *x = wa , *y = wb , *t;
for(i = 0 ; i < m ; i ++ ) ws[i] = 0;;
for(i = 0 ; i < n ; i ++ ) ws[x[i] = r[i]] ++ ;
for(i = 1 ; i < m ; i ++ ) ws[i] += ws[i - 1];
for(i = n - 1 ; i >= 0 ; i -- ) sa[--ws[x[i]]] = i;
for(j = p = 1 ; p < n ; j <<= 1 , m = p)
{
for(p = 0 , i = n - j ; i < n ; i ++ ) y[p ++ ] = i;
for(i = 0 ; i < n ; i ++ ) if(sa[i] - j >= 0) y[p ++ ] = sa[i] - j;
for(i = 0 ; i < n ; i ++ ) wv[i] = x[y[i]];
for(i = 0 ; i < m ; i ++ ) ws[i] = 0;
for(i = 0 ; i < n ; i ++ ) ws[wv[i]] ++ ;
for(i = 1 ; i < m ; i ++ ) ws[i] += ws[i - 1];
for(i = n - 1 ; i >= 0 ; i -- ) sa[--ws[wv[i]]] = y[i];
for(t = x , x = y , y = t , x[sa[0]] = 0 , i = p = 1 ; i < n ; i ++ )
{
if(y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + j] == y[sa[i] + j])
x[sa[i]] = p - 1;
else
x[sa[i]] = p ++ ;
}
}
for(i = 1 ; i < n ; i ++ ) rank[sa[i]] = i;
for(i = p = 0 ; i < n - 1 ; height[rank[i ++ ]] = p)
for(p ? p -- : 0 , j = sa[rank[i] - 1] ; r[i + p] == r[j + p] ; p ++ );
}
bool judge(int m)
{
if(m == 0) return 1;
int i , last = 0;
for(i = 1 ; i <= n ; i ++ )
{
if(height[i] < m)
{
if(i - last >= k) return 1;
last = i;
}
}
return 0;
}
int main()
{
int i , le , ri , mi , ans = 0;
scanf("%d%d" , &n , &k);
for(i = 0 ; i < n ; i ++ )
{
scanf("%d" , &a[i].num);
a[i].rn = i;
}
sort(a , a + n , cmp1);
for(i = 0 ; i < n ; i ++ )
{
if(i == 0 || (i > 0 && a[i].num > a[i - 1].num))
m ++ ;
a[i].tnum = m;
}
sort(a , a + n , cmp2);
for(i = 0 ; i < n ; i ++ )
r[i] = a[i].tnum;
r[n ++ ] = 0;
m ++ ;
da();
le = 0;
ri = n;
while(le <= ri)
{
mi = (le + ri) >> 1;
if(judge(mi))
{
ans = mi;
le = mi + 1;
}
else ri = mi - 1;
}
printf("%d\n" , ans);
return 0;
}
【bzoj1717】[Usaco2006 Dec]Milk Patterns 产奶的模式 后缀数组+离散化的更多相关文章
- bzoj1717: [Usaco2006 Dec]Milk Patterns 产奶的模式(后缀数组+二分)
/* 求可重叠的至少重复K次的最长字串 以1为下标起点,因为a[i]最大到1000000,所以要先离散一下 二分长度len 然后O(n)检验 后看h[i]是否有连续的一段h[i]大于len的,并且h[ ...
- [bzoj1717][Usaco2006 Dec]Milk Patterns 产奶的模式——后缀数组
Brief Description 给定一个字符串,求至少出现k次的最长重复子串. Algorithm Design 先二分答案,然后将后缀分成若干组.判断有没有一个组的后缀个数不小于k.如果有,那么 ...
- BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 [后缀数组]
1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1017 Solved: ...
- 【BZOJ1717】[Usaco2006 Dec]Milk Patterns 产奶的模式 后缀数组
[BZOJ1717][Usaco2006 Dec]Milk Patterns Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的质量 ...
- bzoj1717: [Usaco2006 Dec]Milk Patterns 产奶的模式
后缀数组+二分答案+离散化.(上次写的时候看数据小没离散化然后一直WA...写了lsj师兄的写法. #include<cstdio> #include<cstring> #in ...
- [bzoj1717][Usaco2006 Dec]Milk Patterns 产奶的模式_后缀数组_二分答案
Milk Patterns 产奶的模式 bzoj-1717 Usaco-2006 Dec 题目大意:给定一个字符串,求最长的至少出现了$k$次的子串长度. 注释:$1\le n\le 2\cdot 1 ...
- [bzoj1717][Usaco2006 Dec]Milk Patterns 产奶的模式 (hash构造后缀数组,二分答案)
以后似乎终于不用去学后缀数组的倍增搞法||DC3等blablaSXBK的方法了= = 定义(来自关于后缀数组的那篇国家集训队论文..) 后缀数组:后缀数组SA是一个一维数组,它保存1..n的某个排列S ...
- BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式( 二分答案 + 后缀数组 )
二分答案m, 后缀数组求出height数组后分组来判断. ------------------------------------------------------------ #include&l ...
- BZOJ#1717:[Usaco2006 Dec]Milk Patterns 产奶的模式(后缀数组+单调队列)
1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的 ...
随机推荐
- Tomcat 8.5 基于 Apache Portable Runtime(APR)库性能优化
Tomcat可以使用Apache Portable Runtime来提供卓越的性能及可扩展性,更好地与本地服务器技术的集成.Apache Portable Runtime是一个高度可移植的库,位于Ap ...
- 《图说VR入门》——googleVR入门
本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/52959035 作者:car ...
- 成都Uber优步司机奖励政策(1月17日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- Android AOSP 编译sdk
首先你要有AOSP 工程. 然后执行下面的命令编译sdk. //运行下面的命令得到编译环境 source build/envsetup.sh lunch sdk make sdk 最后文件输出在哪个位 ...
- ORB-SLAM(八)ORBmatcher 特征匹配
该类负责特征点与特征点之间,地图点与特征点之间通过投影关系.词袋模型或者Sim3位姿匹配.用来辅助完成单目初始化,三角化恢复新的地图点,tracking,relocalization以及loop cl ...
- clr via c#读书笔记四:call、callvirt
1.嵌套类,就是定义在类中的类:嵌套类可以访问外部类的方法.属性.字段而不管访问修饰符的限制,但是外部类只能够访问修饰符为public.internal的嵌套类的字段.方法.属性: 2.CLR如何调用 ...
- 后续博客转移到zhylj.cc
此博客暂不更新了 zhylj.cc
- php随机类型验证码
开发使用验证码的意义就是为了区别操作者是人还是机器,防止自动脚本对服务器造成灾难性的攻击 目前有各种各样的验证码种类,譬如:静态字符验证码.算术验证码.拖拽验证码.识别文字或识别物品验证码(高级),下 ...
- (Python爬虫04)了解通用爬虫和聚焦爬虫,还是理论知识.快速入门可以略过的
如果现在的你返回N年前去重新学习一门技能,你会咋做? 我会这么干: ...哦,原来这个本事学完可以成为恋爱大神啊, 我要掌握精髓需要这么几个要点一二三四..... 具体的学习步骤是这样的一二三.... ...
- Vuejs 实现简易 todoList 功能 与 组件
todoList 结合之前 Vuejs 基础与语法 使用 v-model 双向绑定 input 输入内容与数据 data 使用 @click 和 methods 关联事件 使用 v-for 进行数据循 ...