被\(mhr\)的暴力干翻了

这道题做法还是非常好想的

先做一遍差分,在每个串的某尾插入一个特殊字符,再将所有的串拼接在一起

现在的问题就转化为找到一个最长的公共子串使得其出现了\(n\)次,但是在一个串内出现多次出现只算一次

先考虑一下没有第二个限制的做法

那就是最简单的\(SA\)+二分了,就是扫一遍\(height\)数组,之后根据\(height\)进行分组使得一个组内所有的\(height\)都大于等于当前二分出来的\(mid\),之后一个组内有多少个就代表这个子串出现了多少次

现在有了限制,就是不能来自于同一个串

于是我们给每一个\(sa_i\)打一个标记,标记好其来自哪一个数组,之后对于一个组内出现的同一个串内的我们只需要算一次就够了

代码

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #define re register
  5. #define LL long long
  6. #define maxn (1000*100+1000+5)*2
  7. #define max(a,b) ((a)>(b)?(a):(b))
  8. #define min(a,b) ((a)<(b)?(a):(b))
  9. #define pt putchar(1)
  10. inline int read()
  11. {
  12. char c=getchar();int x=0;
  13. while(c<'0'||c>'9') c=getchar();
  14. while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
  15. }
  16. int a[maxn],f[maxn],c[maxn];
  17. int tp[maxn],sa[maxn],rk[maxn],tax[maxn],het[maxn],b[maxn];
  18. int n,m,K,r,t;
  19. inline void qsort()
  20. {
  21. for(re int i=0;i<=K;i++) tax[i]=0;
  22. for(re int i=1;i<=n;i++) tax[rk[i]]++;
  23. for(re int i=1;i<=K;i++) tax[i]+=tax[i-1];
  24. for(re int i=n;i;--i) sa[tax[rk[tp[i]]]--]=tp[i];
  25. }
  26. inline int check(int x)
  27. {
  28. int num=0,now=1;
  29. if(f[sa[1]]) num++,b[f[sa[1]]]++;
  30. for(re int i=2;i<=n;i++)
  31. {
  32. if(het[i]<x)
  33. {
  34. if(num>=m) return 1;
  35. for(re int j=now;j<i;j++) b[f[sa[j]]]=0;
  36. num=0,now=i;
  37. if(f[sa[i]]) num++,b[f[sa[i]]]++;
  38. continue;
  39. }
  40. if(!b[f[sa[i]]]&&f[sa[i]]) b[f[sa[i]]]++,num++;
  41. }
  42. return num>=m;
  43. }
  44. int main()
  45. {
  46. m=read();
  47. for(re int i=1;i<=m;i++)
  48. {
  49. t=read();r=max(t,r);
  50. for(re int j=1;j<=t;j++) a[++n]=read(),f[n]=i;
  51. a[++n]=i+101,f[n]=0;
  52. }
  53. for(re int i=1;i<=n;i++) c[i]=a[i]-a[i-1];
  54. for(re int i=1;i<=n;i++) c[i]+=2001,K=max(c[i],K);
  55. c[1]=0;
  56. for(re int i=1;i<=n;i++) tp[i]=i,rk[i]=c[i];
  57. qsort();
  58. for(re int w=1,p=0;p<n;K=p,w<<=1)
  59. {
  60. p=0;
  61. for(re int i=1;i<=w;i++) tp[++p]=n-w+i;
  62. for(re int i=1;i<=n;i++) if(sa[i]>w) tp[++p]=sa[i]-w;
  63. qsort();
  64. for(re int i=1;i<=n;i++) std::swap(rk[i],tp[i]);
  65. rk[sa[1]]=p=1;
  66. for(re int i=2;i<=n;i++) rk[sa[i]]=(tp[sa[i-1]]==tp[sa[i]]&&tp[sa[i-1]+w]==tp[sa[i]+w])?p:++p;
  67. }
  68. int k=0;
  69. for(re int i=1;i<=n;i++)
  70. {
  71. if(k) --k;
  72. int j=sa[rk[i]-1];
  73. while(c[i+k]==c[j+k]) ++k;
  74. het[rk[i]]=k;
  75. }
  76. int l=1,ans=0;
  77. while(l<=r)
  78. {
  79. int mid=l+r>>1;
  80. if(check(mid)) l=mid+1,ans=mid;
  81. else r=mid-1;
  82. }
  83. printf("%d\n",ans+1);
  84. return 0;
  85. }

【[SDOI2008]Sandy的卡片】的更多相关文章

  1. BZOJ 4698: Sdoi2008 Sandy的卡片

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

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

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

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

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

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

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

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

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

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

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

  7. P2463 [SDOI2008]Sandy的卡片[差分+串拼接后缀数组]

    P2463 [SDOI2008]Sandy的卡片 套路都差不多,都是差分后二分答案找lcp.只是这题要把多个串拼接起来成为一个大串,中间用某些值域中没有的数字相隔(最好间隔符都不一样想想为什么),排序 ...

  8. [bzoj4698][Sdoi2008]Sandy的卡片_后缀数组_二分/单调队列_双指针

    Sandy的卡片 bzoj-4698 Sdoi-2008 题目大意:题目链接. 注释:略. 想法: 这个题跟一个Usaco的题特别像.我们把这些串差分 现在我们要求的就是公共子串且出现次数不少于$k$ ...

  9. [SDOI2008]Sandy的卡片

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

  10. 4698. [SDOI2008]Sandy的卡片【后缀数组】

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

随机推荐

  1. MySQL---4、语句规范

    1.命名规范 (1)库名.表名.(按现在的规范类似; PromoHayaoRecord),数据库名使用小写,字段名必须使用小写字母,并采用下划线分割.关键字与函数名称全部大写.(2)库名.表名.字段名 ...

  2. IIS利用X-Forwarded-For获得来访者的真实IP

    https://help.aliyun.com/knowledge_detail/37948.html

  3. 3.java设计模式-建造者模式

    Java设计模式-建造者模式 在<JAVA与模式>一书中开头是这样描述建造(Builder)模式的: 建造模式是对象的创建模式.建造模式可以将一个产品的内部表象(internal repr ...

  4. Spring入门(二)— IOC注解、Spring测试、AOP入门

    一.Spring整合Servlet背后的细节 1. 为什么要在web.xml中配置listener <listener> <listener-class>org.springf ...

  5. Jquery获取radio选中的值

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. input一些验证

    这篇博文大部分来自于网上,为了方便自己查阅,以及帮助他人. 1.正则验证只能输入正整数:  onkeyup = " if (this.value.length==1) { this.valu ...

  7. laravel之引入图片上传类

    1.在官网http://www.uploadify.com/ 下载插件,flash verison 的版本是免费版 2.解压后将文件夹放置在指定的目录下 3.前端导入css,js文件,可以仿照文件夹中 ...

  8. C语言——循环队列和链队列的基本运算

    // 循环队列#include <stdio.h> #include "SeqQue.h" // 循环队列的基本运算 /* const int maxsize = 20 ...

  9. win10 程序crash后弹出 XXX已停止工作

    需要attach调试器的时候弹出的"XXX已停止工作"很方便, 现在win10默认禁用掉了. 恢复的方法是: win+R 输入gpedit.msc回车 管理模板 -> Win ...

  10. iOS各种profile文件

    iOS是一个非常封闭的系统.授权文件(.mobileprovision)和签名证书文件(.cer)的存在就是为了验证身份信息.一般情况下,比如ssh登陆或者scp需要私钥.公钥对即可,iOS也是基本采 ...