【BZOJ4698】[SDOI2008]Sandy的卡片

题面

flag倒了。

bzoj

洛谷

题解

首先题目的区间加很丑对吧,

将每个串差分一下,就可以转化为

求:

给定\(N\)个串,求他们的最长公共子串。

怎么办呢,按照后缀数组常用套路

我们用不同的未曾用过的字符将这些串连接起来

我们将\(lcp\)大于\(mid\)的串分组

如果一组内串的个数大于等于\(N\)个,就证明可以\(return\;1\)

否则若没有一组大于等于\(N\)返回\(0\)

代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <cmath>
  6. #include <algorithm>
  7. using namespace std;
  8. inline int gi() {
  9. register int data = 0, w = 1;
  10. register char ch = 0;
  11. while (!isdigit(ch) && ch != '-') ch = getchar();
  12. if (ch == '-') w = -1, ch = getchar();
  13. while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
  14. return w * data;
  15. }
  16. const int MAX_N = 2e6 + 5;
  17. int N, T, a[MAX_N], b[MAX_N], vis[MAX_N];
  18. int sa[MAX_N], rnk[MAX_N], lcp[MAX_N];
  19. void GetSA() {
  20. #define cmp(i, j, k) (y[i] == y[j] && y[i + k] == y[j + k])
  21. static int x[MAX_N], y[MAX_N], bln[MAX_N];
  22. int M = 1e6;
  23. for (int i = 1; i <= N; i++) bln[x[i] = a[i]]++;
  24. for (int i = 1; i <= M; i++) bln[i] += bln[i - 1];
  25. for (int i = N; i >= 1; i--) sa[bln[x[i]]--] = i;
  26. for (int k = 1; k <= N; k <<= 1) {
  27. int p = 0;
  28. for (int i = 0; i <= M; i++) y[i] = 0;
  29. for (int i = N - k + 1; i <= N; i++) y[++p] = i;
  30. for (int i = 1; i <= N; i++) if (sa[i] > k) y[++p] = sa[i] - k;
  31. for (int i = 0; i <= M; i++) bln[i] = 0;
  32. for (int i = 1; i <= N; i++) bln[x[y[i]]]++;
  33. for (int i = 1; i <= M; i++) bln[i] += bln[i - 1];
  34. for (int i = N; i >= 1; i--) sa[bln[x[y[i]]]--] = y[i];
  35. swap(x, y); x[sa[1]] = p = 1;
  36. for (int i = 2; i <= N; i++) x[sa[i]] = cmp(sa[i], sa[i - 1], k) ? p : ++p;
  37. if (p >= N) break;
  38. M = p;
  39. }
  40. }
  41. void GetLcp() {
  42. for (int i = 1; i <= N; i++) rnk[sa[i]] = i;
  43. for (int i = 1, j = 0; i <= N; i++) {
  44. if (j) --j;
  45. while (a[i + j] == a[sa[rnk[i] - 1] + j]) ++j;
  46. lcp[rnk[i]] = j;
  47. }
  48. }
  49. int col[MAX_N], tot;
  50. bool check(int v) {
  51. ++tot; int cnt = 0;
  52. for (int i = 1; i <= N; i++) {
  53. if (lcp[i] < v) ++tot, cnt = 0;
  54. if (col[vis[sa[i]]] != tot) col[vis[sa[i]]] = tot, ++cnt;
  55. if (cnt == T) return 1;
  56. }
  57. return 0;
  58. }
  59. const int dlt = 5e4;
  60. int main () {
  61. T = gi();
  62. for (int i = 1; i <= T; i++) {
  63. int m = gi();
  64. for (int j = 1; j <= m; j++) b[j] = gi();
  65. for (int j = 1; j <= m; j++) b[j] = b[j + 1] - b[j] + dlt;
  66. for (int j = 1; j < m; j++) a[++N] = b[j], vis[N] = i;
  67. a[++N] = i + 5e5;
  68. }
  69. GetSA(); GetLcp();
  70. int l = 0, r = N, ans = 0;
  71. while (l <= r) {
  72. int mid = (l + r) >> 1;
  73. if (check(mid)) l = mid + 1, ans = mid;
  74. else r = mid - 1;
  75. }
  76. printf("%d\n", ans + 1);
  77. return 0;
  78. }

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

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

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

  2. BZOJ4698: Sdoi2008 Sandy的卡片

    差分,枚举一个串的所有后缀,暴力在所有其他串中kmp,复杂度$O(nm^2)$. #include<cstdio> const int N=1005; const int M=105; i ...

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

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

  4. BZOJ4698: Sdoi2008 Sandy的卡片(二分 hash)

    题意 题目链接 Sol 用什么后缀数组啊 直接差分之后 二分+hash找最长公共子串就赢了啊... 时间复杂度:\(O(nlogn)\)(不过我写的是两个log..反正也能过) // luogu-ju ...

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

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

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

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

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

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

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

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

  9. BZOJ 4698: Sdoi2008 Sandy的卡片

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

随机推荐

  1. Unable to perform unmarshalling at line number 16 and column 63 in RESOURCE hibernate.cfg.xml. Message: cvc-elt.1: 找不到元素 'hibernate-configuration' 的声明。

    七月 02, 2017 4:32:37 下午 org.hibernate.Version logVersionINFO: HHH000412: Hibernate Core {5.2.10.Final ...

  2. ApplicationEventMulticaster接口笔记

    ApplicationEventMulticaster 这个接口可以管理很多个ApplicationListener对象.并将事件发布给这些监听器. ApplicationEventPublisher ...

  3. Java并发案例01---多线程之死锁

    多线程之死锁案例一 package example; /** * 模拟死锁 * @author maple * */ public class DeadLock { public int flag = ...

  4. win10里如何在中文输入法里添加美式键盘

    在控制面板打开“时钟.语言和区域”设置界面,选中“语言”设置  “语言”设置里点击“添加语言” 在添加语言设置里选择“英语”,并点击“打开”按钮,在“区域变量”设置页面里选择“英语(美国)” ,并点击 ...

  5. php redis中文手册

    phpredis是php的一个扩展,效率是相当高有链表排序功能,对创建内存级的模块业务关系 很有用;以下是redis官方提供的命令使用技巧: 下载地址如下: https://github.com/ow ...

  6. IIs和ftp

    简单的说,FTP就是完成两台计算机之间的拷贝,从远程计算机拷贝文件至自己的计算机上,称之为“下载(download)”文件.若将文件从自己计算机中拷贝至远程计算机上,则称之为“上载(upload)”文 ...

  7. SpringBoot实战(九)之Validator

    表单验证,是最为常见的,今天演示的是利用hibernate-validtor进行校验,有的时候,虽然前端方面通过jQuery或者require.js校验框架进行校验,可以减轻服务器的压力和改善用户体验 ...

  8. java读写本地xml

    <?xml version="1.0" encoding="UTF-8" standalone="no"?> <confi ...

  9. 跳转到AppStore下载app

    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://itunes.apple.com/cn/ap ...

  10. 【luogu P1608 路径统计】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1608 补上一发最短路计数! 感谢王强qwqqqq @Lance1ot #include <queue& ...