【BZOJ4698】Sdoi2008 Sandy的卡片

Description

Sandy和Sue的热衷于收集干脆面中的卡片。然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡片兑换超炫的人物模型。每一张卡片都由一些数字进行标记,第i张卡片的序列长度为Mi,要想兑换人物模型,首先必须要集够N张卡片,对于这N张卡片,如果他们都有一个相同的子串长度为k,则可以兑换一个等级为k的人物模型。相同的定义为:两个子串长度相同且一个串的全部元素加上一个数就会变成另一个串。Sandy的卡片数远远小于要求的N,于是Sue决定在Sandy的生日将自己的卡片送给Sandy,在Sue的帮助下,Sandy终于集够了N张卡片,但是,Sandy并不清楚他可以兑换到哪个等级的人物模型,现在,请你帮助Sandy和Sue,看看他们最高能够得到哪个等级的人物模型。

Input

第一行为一个数N,表示可以兑换人物模型最少需要的卡片数,即Sandy现在有的卡片数
第i+1行到第i+N行每行第一个数为第i张卡片序列的长度Mi,之后j+1到j+1+Mi个数,用空格分隔,分别表示序列中
的第j个数
n<=1000,M<=1000,2<=Mi<=101

Output

一个数k,表示可以获得的最高等级。

Sample Input

2
2 1 2
3 4 5 9

Sample Output

2

题解:本题让我们求的是变化趋势相同的子串,那么我们直接求出每个数串相邻两项的差,然后用这个差来求最长公共子串就行了。当然,这些差可能会有负值,那就集体减去最小值-1(防止出现0)就行了。先把这些串全部连接起来,中间用极大值隔开,求出sa和height。然后再height数组上维护这样一个区间,使得这个区间中的后缀在每个数串中都出现过,并且区间长度尽可能短,然后从左向右平移这个区间,用RMQ维护区间中最小的height,答案就是这个最大的最小值+1。当然这题也可以二分答案来做。

因为RMQ写错竟然调了一天,感觉我有几年没写RMQ了。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. using namespace std;
  5. const int maxn=200010;
  6. int minn,maxx;
  7. int r[maxn],ra[maxn],rb[maxn],st[maxn],sa[maxn],rank[maxn],h[maxn];
  8. int N,M[maxn],sm[maxn],bel[maxn],n,m,v[maxn];
  9. int s[maxn],sum,ans;
  10. int dp[maxn][20],Log[maxn];
  11. void work()
  12. {
  13. int i,j,k,*x=ra,*y=rb,p;
  14. for(i=0;i<n;i++) st[x[i]=r[i]]++;
  15. for(i=1;i<m;i++) st[i]+=st[i-1];
  16. for(i=n-1;i>=0;i--) sa[--st[x[i]]]=i;
  17. for(j=p=1;p<n;j<<=1,m=p)
  18. {
  19. for(i=n-j,p=0;i<n;i++) y[p++]=i;
  20. for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
  21. for(i=0;i<m;i++) st[i]=0;
  22. for(i=0;i<n;i++) st[x[y[i]]]++;
  23. for(i=1;i<m;i++) st[i]+=st[i-1];
  24. for(i=n-1;i>=0;i--) sa[--st[x[y[i]]]]=y[i];
  25. for(swap(x,y),i=p=1,x[sa[0]]=0;i<n;i++)
  26. x[sa[i]]=(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+j]==y[sa[i]+j])?p-1:p++;
  27. }
  28. for(i=1;i<n;i++) rank[sa[i]]=i;
  29. for(i=k=0;i<n-1;h[rank[i++]]=k)
  30. for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
  31. }
  32. void rmq()
  33. {
  34. int i,j;
  35. for(i=2;i<n;i++) Log[i]=Log[i>>1]+1;
  36. for(i=1;i<n;i++) dp[i][0]=h[i];
  37. for(j=1;(1<<j)<n;j++)
  38. for(i=1;i+(1<<j)-1<n;i++)
  39. dp[i][j]=min(dp[i][j-1],dp[i+(1<<j-1)][j-1]);
  40. }
  41. int getmin(int a,int b)
  42. {
  43. int k=Log[b-a+1];
  44. return min(dp[a][k],dp[b-(1<<k)+1][k]);
  45. }
  46. int main()
  47. {
  48. scanf("%d",&N);
  49. int i,j,now=0;
  50. sm[0]=-1;
  51. for(i=1;i<=N;i++)
  52. {
  53. scanf("%d",&M[i]);
  54. sm[i]=sm[i-1]+M[i];
  55. scanf("%d",&v[1]);
  56. for(j=2;j<=M[i];j++)
  57. {
  58. bel[now]=i;
  59. scanf("%d",&v[j]);
  60. r[now]=v[j]-v[j-1];
  61. maxx=max(maxx,r[now]);
  62. minn=min(minn,r[now++]);
  63. }
  64. now++;
  65. }
  66. for(i=0;i<sm[N];i++) r[i]-=minn-1;
  67. r[sm[N]]=0;
  68. m=maxx-minn+1;
  69. for(i=1;i<N;i++) r[sm[i]]=m+1;
  70. n=sm[N]+1,m+=2;
  71. work();
  72. rmq();
  73. for(i=1;i<n;i++)
  74. {
  75. if(!s[bel[sa[i]]])
  76. {
  77. if(sum==N-1) break;
  78. sum++;
  79. }
  80. s[bel[sa[i]]]++;
  81. }
  82. now=1;
  83. for(;i<n;i++)
  84. {
  85. if(!bel[sa[i]]) break;
  86. s[bel[sa[i]]]++;
  87. while(s[bel[sa[now]]]>1) s[bel[sa[now++]]]--;
  88. ans=max(ans,getmin(now+1,i));
  89. }
  90. printf("%d",ans+1);
  91. return 0;
  92. }

【BZOJ4698】Sdoi2008 Sandy的卡片 后缀数组+RMQ的更多相关文章

  1. BZOJ 4698: Sdoi2008 Sandy的卡片 后缀数组 + RMQ + 查分

    题目描述 Sandy和Sue的热衷于收集干脆面中的卡片. 然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡片兑换超炫的人物模型. 每一张卡片都由一些数字进行标记,第i张卡片的 ...

  2. BZOJ4698: Sdoi2008 Sandy的卡片(后缀数组 二分)

    题意 题目链接 Sol 不要问我为什么发两篇blog,就是为了骗访问量 后缀数组的也比较好想,先把所有位置差分,然后在height数组中二分就行了 数据好水啊 // luogu-judger-enab ...

  3. 【BZOJ-4698】Sandy的卡片 后缀数组

    4698: Sdoi2008 Sandy的卡片 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 140  Solved: 55[Submit][Stat ...

  4. 【bzoj4698】[Sdoi2008] Sandy的卡片 后缀数组

    题目描述 Sandy和Sue的热衷于收集干脆面中的卡片.然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡片兑换超炫的人物模型.每一张卡片都由一些数字进行标记,第i张卡片的序列 ...

  5. SDOI2008 Sandy的卡片( 后缀数组 )

    求出后缀数组, 然后二分答案, 对height数组分组检验答案. 时间复杂度O(|S| log|S|) ------------------------------------------------ ...

  6. BZOJ 4698: Sdoi2008 Sandy的卡片(后缀数组+差分+二分答案)

    传送门 解题思路 看到一个子串加一个数字到另一个子串,自然可以想到差分.然后要把所有串都拼起来,求出\(height\)数组后可以二分答案来做,每次二分一个答案后统计一下连续的\(height> ...

  7. [BZOJ4698][SDOI2008]Sandy的卡片(后缀自动机)

    差分之后就是求多串LCS. 对其中一个串建SAM,然后把其它串放在上面跑. 对SAM上的每个状态都用f[x]记录这个状态与当前串的最长匹配长度,res[x]是对每次的f[x]取最小值.答案就是res[ ...

  8. 洛谷P2463 [SDOI2008]Sandy的卡片(后缀数组SA + 差分 + 二分答案)

    题目链接:https://www.luogu.org/problem/P2463 [题意] 求出N个串中都出现的相同子串的最长长度,相同子串的定义如题:所有元素加上一个数变成另一个,则这两个串相同,可 ...

  9. BZOJ 4698: Sdoi2008 Sandy的卡片 [后缀自动机]

    4698: Sdoi2008 Sandy的卡片 题意:差分后就是多个串LCS SAM+map大法好 模板打错 智力-2 #include <iostream> #include <c ...

随机推荐

  1. tar -h 参数

    1.1.1 tar命令参数-h,-h参数会把软链接指向的文件也打包. [root@ob2 mytmp]# ll total 8 -rw-r--r--. 1 root root 910 Aug 12 2 ...

  2. MongoDB Shell 了解使用

    配置环境变量 WIN10系统:右键单击"此电脑"--属性--高级系统设置--高级--环境变量,添加C:\Program Files\MongoDB\Server\3.0\bin 如 ...

  3. Golang map 如何进行删除操作?

    Cyeam 关注 2017.11.02 10:02* 字数 372 阅读 2784评论 0喜欢 3 map 的删除操作 Golang 内置了哈希表,总体上是使用哈希链表实现的,如果出现哈希冲突,就把冲 ...

  4. Nutch系列1:简介

    由Java实现的,开放源代码(open-source)的web搜索引擎. Nutch 致力于让每个人都能很容易, 同时花费很少就可以配置世界一流的Web搜索引擎. 为了完成这一宏伟的目标, Nutch ...

  5. 【转】苹果App Store新规:6月1日后所有应用必须支持IPv6-only网络

    在WWDC2015上苹果宣布iOS9将支持纯IPv6的网络服务.2016年初开始所有提交到App Store的应用必须支持IPv6.为确保现有的应用是兼容的,我们需要注意下面几点. 不建议使用底层的网 ...

  6. 关于在Android中访问和使用到上下文变量

    在监听器内部实现类中要引用上下文变量this的时候 一.采用类名.this的方法 FActivity.this 二.采用全局变量当做中间变量 1.先定义一个全局变量 private Context m ...

  7. FFmpeg在Android上的移植优化步骤

    http://blog.csdn.net/feixiang_john/article/details/7894188 从事多媒体软件开发的人几乎没有不知道FFmpeg的,很多视频播放器都是基于FFmp ...

  8. javascript -- js正则表达式

    正则表达式可以:  1.测试字符串的某个模式.例如,可以对一个输入字符串进行测试,看在该字符串是否存在一个电话号码模式或一个信用卡号码模式.这称为数据有效性验证 2.替换文本.可以在文档中使用一个正则 ...

  9. linux -- Ubuntuserver图形界面下安装、配置lampp、phpmyadmin

    PHP开发和服务器运行环境首选LAMP组合,即Linux+Apache+Mysql+Php/Perl/Python,能最优化服务器性能.如何在本地电脑Ubuntu 中安装和配置LAMP环境搭建?Ubu ...

  10. 结构型模式概述(Structural Pattern)

    结构型模式可以描述两种不同的东西:类与类的实例.结构型模式可以分为类结构型模式和对象结构型模式. 类结构型模式关心类的组合,可以由多个类组合成一个更大的系统,在类结构型模式中只存在继承关系和实现关系: ...