题目描述

农夫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,无论如何也无法进行,所以加上特判。

  1. #include <cstdio>
  2. #include <algorithm>
  3. using namespace std;
  4. #define N 20005
  5. int ws[N] , wv[N] , wa[N] , wb[N] , sa[N] , r[N] , n , m , k;
  6. int rank[N] , height[N];
  7. struct data
  8. {
  9. int num , rn , tnum;
  10. }a[20001];
  11. bool cmp1(data a , data b)
  12. {
  13. return a.num < b.num;
  14. }
  15. bool cmp2(data a , data b)
  16. {
  17. return a.rn < b.rn;
  18. }
  19. void da()
  20. {
  21. int i , j , p , *x = wa , *y = wb , *t;
  22. for(i = 0 ; i < m ; i ++ ) ws[i] = 0;;
  23. for(i = 0 ; i < n ; i ++ ) ws[x[i] = r[i]] ++ ;
  24. for(i = 1 ; i < m ; i ++ ) ws[i] += ws[i - 1];
  25. for(i = n - 1 ; i >= 0 ; i -- ) sa[--ws[x[i]]] = i;
  26. for(j = p = 1 ; p < n ; j <<= 1 , m = p)
  27. {
  28. for(p = 0 , i = n - j ; i < n ; i ++ ) y[p ++ ] = i;
  29. for(i = 0 ; i < n ; i ++ ) if(sa[i] - j >= 0) y[p ++ ] = sa[i] - j;
  30. for(i = 0 ; i < n ; i ++ ) wv[i] = x[y[i]];
  31. for(i = 0 ; i < m ; i ++ ) ws[i] = 0;
  32. for(i = 0 ; i < n ; i ++ ) ws[wv[i]] ++ ;
  33. for(i = 1 ; i < m ; i ++ ) ws[i] += ws[i - 1];
  34. for(i = n - 1 ; i >= 0 ; i -- ) sa[--ws[wv[i]]] = y[i];
  35. for(t = x , x = y , y = t , x[sa[0]] = 0 , i = p = 1 ; i < n ; i ++ )
  36. {
  37. if(y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + j] == y[sa[i] + j])
  38. x[sa[i]] = p - 1;
  39. else
  40. x[sa[i]] = p ++ ;
  41. }
  42. }
  43. for(i = 1 ; i < n ; i ++ ) rank[sa[i]] = i;
  44. for(i = p = 0 ; i < n - 1 ; height[rank[i ++ ]] = p)
  45. for(p ? p -- : 0 , j = sa[rank[i] - 1] ; r[i + p] == r[j + p] ; p ++ );
  46. }
  47. bool judge(int m)
  48. {
  49. if(m == 0) return 1;
  50. int i , last = 0;
  51. for(i = 1 ; i <= n ; i ++ )
  52. {
  53. if(height[i] < m)
  54. {
  55. if(i - last >= k) return 1;
  56. last = i;
  57. }
  58. }
  59. return 0;
  60. }
  61. int main()
  62. {
  63. int i , le , ri , mi , ans = 0;
  64. scanf("%d%d" , &n , &k);
  65. for(i = 0 ; i < n ; i ++ )
  66. {
  67. scanf("%d" , &a[i].num);
  68. a[i].rn = i;
  69. }
  70. sort(a , a + n , cmp1);
  71. for(i = 0 ; i < n ; i ++ )
  72. {
  73. if(i == 0 || (i > 0 && a[i].num > a[i - 1].num))
  74. m ++ ;
  75. a[i].tnum = m;
  76. }
  77. sort(a , a + n , cmp2);
  78. for(i = 0 ; i < n ; i ++ )
  79. r[i] = a[i].tnum;
  80. r[n ++ ] = 0;
  81. m ++ ;
  82. da();
  83. le = 0;
  84. ri = n;
  85. while(le <= ri)
  86. {
  87. mi = (le + ri) >> 1;
  88. if(judge(mi))
  89. {
  90. ans = mi;
  91. le = mi + 1;
  92. }
  93. else ri = mi - 1;
  94. }
  95. printf("%d\n" , ans);
  96. return 0;
  97. }

【bzoj1717】[Usaco2006 Dec]Milk Patterns 产奶的模式 后缀数组+离散化的更多相关文章

  1. bzoj1717: [Usaco2006 Dec]Milk Patterns 产奶的模式(后缀数组+二分)

    /* 求可重叠的至少重复K次的最长字串 以1为下标起点,因为a[i]最大到1000000,所以要先离散一下 二分长度len 然后O(n)检验 后看h[i]是否有连续的一段h[i]大于len的,并且h[ ...

  2. [bzoj1717][Usaco2006 Dec]Milk Patterns 产奶的模式——后缀数组

    Brief Description 给定一个字符串,求至少出现k次的最长重复子串. Algorithm Design 先二分答案,然后将后缀分成若干组.判断有没有一个组的后缀个数不小于k.如果有,那么 ...

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

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

  4. 【BZOJ1717】[Usaco2006 Dec]Milk Patterns 产奶的模式 后缀数组

    [BZOJ1717][Usaco2006 Dec]Milk Patterns Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的质量 ...

  5. bzoj1717: [Usaco2006 Dec]Milk Patterns 产奶的模式

    后缀数组+二分答案+离散化.(上次写的时候看数据小没离散化然后一直WA...写了lsj师兄的写法. #include<cstdio> #include<cstring> #in ...

  6. [bzoj1717][Usaco2006 Dec]Milk Patterns 产奶的模式_后缀数组_二分答案

    Milk Patterns 产奶的模式 bzoj-1717 Usaco-2006 Dec 题目大意:给定一个字符串,求最长的至少出现了$k$次的子串长度. 注释:$1\le n\le 2\cdot 1 ...

  7. [bzoj1717][Usaco2006 Dec]Milk Patterns 产奶的模式 (hash构造后缀数组,二分答案)

    以后似乎终于不用去学后缀数组的倍增搞法||DC3等blablaSXBK的方法了= = 定义(来自关于后缀数组的那篇国家集训队论文..) 后缀数组:后缀数组SA是一个一维数组,它保存1..n的某个排列S ...

  8. BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式( 二分答案 + 后缀数组 )

    二分答案m, 后缀数组求出height数组后分组来判断. ------------------------------------------------------------ #include&l ...

  9. BZOJ#1717:[Usaco2006 Dec]Milk Patterns 产奶的模式(后缀数组+单调队列)

    1717: [Usaco2006 Dec]Milk Patterns 产奶的模式 Description 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的 ...

随机推荐

  1. eclipse注释任务标记

     一.概述 TODO: + 说明: 如果代码中有该标识,说明在标识处有功能代码待编写,待实现的功能在说明中会简略说明. FIXME: + 说明: 如果代码中有该标识,说明标识处代码需要修正,甚至代码是 ...

  2. java 类装饰

    package TestIo; public class Test8 { public static void main(String[] args) { System.out.println(&qu ...

  3. Web自动化测试环境搭建1(基于firefox火狐浏览器)

    自动化测试是时代趋势,因此很多测试人员开始研究自动化测试,web自动化测试化测试并不难,但是很多人都是被挡在了环境搭建这一步,后面学习激情全无,这里,韬哥手把手教大家搭建火狐浏览器下的自动化测试环境( ...

  4. Python字典操作大全

    //2018.11.6 Python字典操作 1.对于python编程里面字典的定义有以下几种方法: >>> a = dict(one=1, two=2, three=3) > ...

  5. java后台接受web前台传递的数组参数

    前台发送:&warning_type[]=1,2 &warning_type=1,2 后台接收:(@RequestParam(value = "param[]") ...

  6. 【if控制器】-(某种情况成立就执行的场景)

    if 控制器   一般来判断某种特殊情况 成立,就执行. JEXL Expression to evaluate:此处直接填写需要进行判断的表达式即可 表达式支持: ==  是否等于,如${__jex ...

  7. 凸包算法(Graham扫描法)详解

    先说下基础知识,不然不好理解后面的东西 两向量的X乘p1(x1,y1),p2(x2,y2) p1Xp2如果小于零则说明  p1在p2的逆时针方向 如果大于零则说明 p1在p2的顺时针方向 struct ...

  8. gitolite 丢失管理密钥/访问权限 解决办法

    登录到服务器. 使用完整路径克隆管理员仓库: git clone $HOME/repositories/gitolite-admin.git temp cd gitolite-admin/conf v ...

  9. Python字符串所有操作函数

    name = "my \tname is {name} and i am {year} old" print(name.capitalize())#首字母大写 print(name ...

  10. Trie 树——搜索关键词提示

    当你在搜索引擎中输入想要搜索的一部分内容时,搜索引擎就会自动弹出下拉框,里面是各种关键词提示,这个功能是怎么实现的呢?其实底层最基本的就是 Trie 树这种数据结构. 1. 什么是 "Tri ...