http://www.lydsy.com/JudgeOnline/problem.php?id=4698

https://www.luogu.org/problemnew/show/P2463#sub

Sandy和Sue的热衷于收集干脆面中的卡片。

然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡片兑换超炫的人物模型。

每一张卡片都由一些数字进行标记,第i张卡片的序列长度为Mi,要想兑换人物模型,首先必须要集够N张卡片,对于这N张卡片,如果他们都有一个相同的子串长度为k,则可以兑换一个等级为k的人物模型。相同的定义为:两个子串长度相同且一个串的全部元素加上一个数就会变成另一个串。

Sandy的卡片数远远小于要求的N,于是Sue决定在Sandy的生日将自己的卡片送给Sandy,在Sue的帮助下,Sandy终于集够了N张卡片,但是,Sandy并不清楚他可以兑换到哪个等级的人物模型,现在,请你帮助Sandy和Sue,看看他们最高能够得到哪个等级的人物模型。

如果你做过POJ2774:Long Long MessagePOJ1743:Musical Theme的话,这道题想起来就很容易了。

将所有数差分后接起来(中间加一个大数作为分隔符),后缀数组和height数组预处理,然后二分答案,按照height分组找是否存在。

PS:差分处理具体看POJ1743:Musical Theme。

(吐槽:最开始我还想把所有数段的区间记下来,然后用log查找一个后缀属于哪个串,越想越不对劲看了题解,果然我还是太naive了,直接开个id数组记录每个数属于哪个数段就行了吗!)

(果然我容易思维定式。)

(姑且也算是不看题解1A233。)

  1. #include<cstdio>
  2. #include<cmath>
  3. #include<iostream>
  4. #include<vector>
  5. #include<cstring>
  6. #include<algorithm>
  7. #include<cctype>
  8. using namespace std;
  9. typedef long long ll;
  10. const int N=1e6+;
  11. const int big=;
  12. int s[N],a[N],cnt=big*+;
  13. int n,m,t,rk[N],sa[N],w[N],height[N],id[N];
  14. bool in[];
  15. inline bool pan(int *x,int i,int j,int k){
  16. int ti=i+k<n?x[i+k]:-;
  17. int tj=j+k<n?x[j+k]:-;
  18. return ti==tj&&x[i]==x[j];
  19. }
  20. void SA_init(){
  21. int *x=rk,*y=height,r=cnt;
  22. for(int i=;i<r;i++)w[i]=;
  23. for(int i=;i<n;i++)w[s[i]]++;
  24. for(int i=;i<r;i++)w[i]+=w[i-];
  25. for(int i=n-;i>=;i--)sa[--w[s[i]]]=i;
  26. r=;x[sa[]]=;
  27. for(int i=;i<n;i++)
  28. x[sa[i]]=s[sa[i]]==s[sa[i-]]?r-:r++;
  29. for(int k=;r<n;k<<=){
  30. int yn=;
  31. for(int i=n-k;i<n;i++)y[yn++]=i;
  32. for(int i=;i<n;i++)
  33. if(sa[i]>=k)y[yn++]=sa[i]-k;
  34. for(int i=;i<r;i++)w[i]=;
  35. for(int i=;i<n;i++)w[x[y[i]]]++;
  36. for(int i=;i<r;i++)w[i]+=w[i-];
  37. for(int i=n-;i>=;i--)sa[--w[x[y[i]]]]=y[i];
  38. swap(x,y);r=;x[sa[]]=;
  39. for(int i=;i<n;i++)
  40. x[sa[i]]=pan(y,sa[i],sa[i-],k)?r-:r++;
  41. }
  42. }
  43. void height_init(){
  44. int i,j,k=;
  45. for(int i=;i<=n;i++)rk[sa[i]]=i;
  46. for(int i=;i<n;i++){
  47. if(k)k--;
  48. int j=sa[rk[i]-];
  49. while(s[i+k]==s[j+k])k++;
  50. height[rk[i]]=k;
  51. }
  52. }
  53. bool check(int k){
  54. int sum=;
  55. in[id[sa[]]]=;
  56. for(int i=;i<=n;i++){
  57. if(height[i]>=k){
  58. if(!in[id[sa[i]]]){
  59. sum++;
  60. in[id[sa[i]]]=;
  61. }
  62. }else{
  63. memset(in,,sizeof(in));
  64. sum=;
  65. in[id[sa[i]]]=;
  66. }
  67. if(sum==t)return ;
  68. }
  69. return ;
  70. }
  71. int main(){
  72. scanf("%d",&t);
  73. for(int i=;i<=t;i++){
  74. scanf("%d",&m);
  75. for(int j=n;j<=n+m-;j++){
  76. scanf("%d",&a[j]);
  77. }
  78. for(int j=n+;j<=n+m-;j++){
  79. s[j-]=a[j]-a[j-]+big;
  80. id[j-]=i;
  81. }
  82. s[n+m-]=cnt++;
  83. n+=m;
  84. }
  85. s[n++]=;
  86. SA_init();
  87. n--;
  88. height_init();
  89. int l=,r=;
  90. while(l<r){
  91. int mid=(l+r+)>>;
  92. if(check(mid))l=mid;
  93. else r=mid-;
  94. }
  95. printf("%d\n",l+);
  96. return ;
  97. }

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

BZOJ4698 & 洛谷2463:[SDOI2008]Sandy的卡片——题解的更多相关文章

  1. 洛谷 P2463 [SDOI2008]Sandy的卡片 解题报告

    P2463 [SDOI2008]Sandy的卡片 题意 给\(n(\le 1000)\)串,定义两个串相等为"长度相同,且一个串每个数加某个数与另一个串完全相同",求所有串的最长公 ...

  2. [洛谷P2463][SDOI2008]Sandy的卡片

    题目大意:有$n$个字符串,求这$n$个字符串中最长的相似公共字串,相似的定义是加上一个数后相同 题解:差分,建广义后缀自动机,然后求出每个点在多少个字符串中出现过,若在$n$个中都出现,就更新答案 ...

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

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

  4. 洛咕 P2463 [SDOI2008]Sandy的卡片

    哈希水过. 首先这是一段delta相同的序列,按照套路差分一下,b[i]=a[i]-a[i-1],然后就是这些序列的最长公共子段 由于数据范围很小,就可以二分,枚举第一个序列的子段然后每个子序列暴力c ...

  5. luogu 2463 [SDOI2008]Sandy的卡片 kmp || 后缀数组 n个串的最长公共子串

    题目链接 Description 给出\(n\)个序列.找出这\(n\)个序列的最长相同子串. 在这里,相同定义为:两个子串长度相同且一个串的全部元素加上一个数就会变成另一个串. 思路 参考:hzwe ...

  6. 【BZOJ4698】[SDOI2008]Sandy的卡片

    [BZOJ4698][SDOI2008]Sandy的卡片 题面 flag倒了. bzoj 洛谷 题解 首先题目的区间加很丑对吧, 将每个串差分一下,就可以转化为 求: 给定\(N\)个串,求他们的最长 ...

  7. 【BZOJ4698】Sdoi2008 Sandy的卡片 后缀数组+RMQ

    [BZOJ4698]Sdoi2008 Sandy的卡片 Description Sandy和Sue的热衷于收集干脆面中的卡片.然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡 ...

  8. bzoj4698 / P2463 [SDOI2008]Sandy的卡片

    P2463 [SDOI2008]Sandy的卡片 直接二分长度暴力匹配....... 跑的还挺快 (正解是后缀数组的样子) #include<iostream> #include<c ...

  9. BZOJ 4698: Sdoi2008 Sandy的卡片

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

随机推荐

  1. windown reids

    记录Windown安装Redis和php_redis扩展 和Linux系统不同windown中不需要编译安装:只需要下对版本拖拽过去即可: 首先安装redis服务: 可以百度下一个,只要注意系统版本即 ...

  2. KubeCon深度洞察 | KubeEdge开源首秀

    以下内容根据华为云DJ在KubeCon Shanghai Demo Session演讲实录整理而成. KubeEdge Demo Show 11月15日上午Huawei宣布了KubeEdge项目开源, ...

  3. uvaoj1339 - Ancient Cipher(思维题,排序,字符串加密)

    https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  4. Java 语法基础

    一 关键字 关键字: 其实就是某种语言赋予了特殊含义的单词 保留字: 其实就是还没有赋予特殊含义 但是准备日后要使用过的单词 二 标示符 标示符: 其实就是在程序中自定义的名词 比如类名, 变量名, ...

  5. 更新字典 (Updating a Dictionary,UVa12504)

    题目描述: 解题思路: 1.根据:和,获得字符串 2.使用两个map进行比较: #include <iostream> #include <algorithm> #includ ...

  6. 数数字 (Digit Counting,ACM/ICPC Dannang 2007 ,UVa1225)

    题目描述:算法竞赛入门经典习题3-3 #include <stdio.h> #include <string.h> int main(int argc, char *argv[ ...

  7. 【Coursera-ML-Notes】线性回归(下)

    模型表示 多变量的线性回归也叫做"多元线性回归".首先还是先明确几个符号的含义. \(x{^{(i)}_j}\):第i个训练样本的第j个特征,比如面积,楼层,客厅数 \(x^{(i ...

  8. @Configuration和@Bean

    @Configuration可理解为用spring的时候xml里面的标签 @Bean可理解为用spring的时候xml里面的标签 Spring Boot不是spring的加强版,所以@Configur ...

  9. 基于Kubernetes(k8s)网络方案演进

    VIP PaaS在接近两年时间里,基于kubernetes主要经历四次网络方案的变迁: 1. kubernetes + flannel 2. 基于Docker libnetwork的网络定制 3. k ...

  10. svn升级(mac)

    原文链接:http://www.jianshu.com/p/c81712ecccb8 升级前 svn版本1.7.20 升级之后 1.9.2 步骤: 1. 下载最新版svn,链接:http://www. ...