题目链接 \(Click\) \(Here\)

真的好麻烦啊。。事实证明,理解是理解,一定要认认真真把板子打牢,不然调锅的时候真的会很痛苦。。(最好是八分钟能无脑把\(SA\)码对的程度\(QAQ\))

这个题最开始我想的是\(RMQ\)遍历每一个子区间,但是意识到复杂度是\(O(N^2)\)然后就\(GG\)了。怎么说呢,后缀数组和二分似乎是很常见的组合(和莫队也是?),这个题只需要在\(height\)数组里二分\(lcp\)长度即可,\(check\)函数里面处理一下,要让区间内所有原串都有至少一个子串。

#include <bits/stdc++.h>
using namespace std; const int N = 200010; int s[N], id[N];
int n, m, num, len, tot = 10000;
int sa[N], tp[N], rk[N], _rk[N], bin[N], height[N]; void get_height (int n) {
int k = 0;
for (int i = 1; i <= n; ++i) {
if (k != 0) k--;
int j = sa[rk[i] - 1];
while (s[i + k] == s[j + k]) k++;
height[rk[i]] = k;
}
} void base_sort (int n, int m) {
for (int i = 0; i <= m; ++i) bin[i] = 0;
for (int i = 1; i <= n; ++i) bin[rk[tp[i]]]++;
for (int i = 1; i <= m; ++i) bin[i] += bin[i - 1];
for (int i = n; i >= 1; --i) sa[bin[rk[tp[i]]]--] = tp[i];
} void suffix_sort (int n, int m) {
for (int i = 1; i <= n; ++i) {
rk[i] = s[i];
tp[i] = i;
}
base_sort (n, m);
for (int w = 1; w <= n; w <<= 1) {
int cnt = 0;
for (int i = n - w + 1; i <= n; ++i) {
tp[++cnt] = i;
}
for (int i = 1; i <= n; ++i) {
if (sa[i] > w) {
tp[++cnt] = sa[i] - w;
}
}
base_sort (n, m);
memcpy (_rk, rk, sizeof (rk));
rk[sa[1]] = cnt = 1;
for (int i = 2; i <= n; ++i) {
rk[sa[i]] = _rk[sa[i]] == _rk[sa[i - 1]] && _rk[sa[i] + w] == _rk[sa[i - 1] + w] ? cnt : ++cnt;
}
if (cnt == n) break;
m = cnt;
}
} bool vis[1010]; int sta[N], top = 0; bool can_use (int l) {
while (top) vis[sta[top--]] = false;
for (int i = 1; i <= len; ++i) {
if (height[i] < l) {
while (top) vis[sta[top--]] = false;
}
if (!vis[id[sa[i]]]) {
vis[id[sa[i]]] = true;
sta[++top] = id[sa[i]];
if (top == n) return true;
}
}
return false;
} int main () {
cin >> n;
int ban = 2000;
for (int i = 1; i <= n; ++i) {
cin >> m;
for (int j = 1; j <= m; ++j) {
cin >> s[++len]; //把所有的字符串整合到一个里
id[len] = i; // 表明主权(len号后缀(的lcp)属于串i)
}
s[++len] = ++ban; //隔开
}
for (int i = len; i >= 1; --i) {
s[i] = s[i] - s[i - 1] + 4000;
}
suffix_sort (len, 10000);
get_height (len);
int l = 0, r = len;
while (l < r) {
int mid = (l + r + 1) >> 1;
if (can_use (mid)) {
l = mid;
} else {
r = mid - 1;
}
}
cout << l + 1 << endl;
}

Luogu P2463 [SDOI2008]Sandy的卡片的更多相关文章

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

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

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

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

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

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

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

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

  5. P2463 [SDOI2008]Sandy的卡片

    写一种\(O(nm)\)的做法,也就是\(O(\sum 串长)\)的. 先通过差分转化,把每个数变成这个数与上一个数的差,第一个数去掉,答案就是最长公共子串+1 按照套路把所有串拼起来,中间加一个分隔 ...

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

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

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

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

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

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

  9. BZOJ 4698: Sdoi2008 Sandy的卡片

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

随机推荐

  1. HTTP协议 - 使用php模拟get/post请求

    首先 有个疑问, 是不是只有浏览器才能发送http 请求? 答案肯定是错的,第一篇就说了,http是由请求行,请求头,请求主体三个部分组成,那么我们可不可以用代码来模拟一下get和post请求呢: 首 ...

  2. crontab注意%

    %在其中有特殊含义表示开始新行 十分坑 例子:写一个定时任务用到date命令 crontab -e * * * * * date +%F >> /tmp/time.log 查看我们的cro ...

  3. hibernate主配置文件的配置

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuratio ...

  4. hdu-5687(字典树)

    题意:中文题: 解题思路:增加和查询就不说了,标准操作,就是删除操作:删除操作的时候,我们把给定字符串先在字典树中遍历一遍,然后算出这个字符串最后一个字符的出现次数,然后在遍历一遍,每个节点都减去这个 ...

  5. [离散时间信号处理学习笔记] 7. z变换

    z变换及其收敛域 回顾前面的文章,序列$x[n]$的傅里叶变换(实际上是DTFT,由于本书把它叫做序列的傅里叶变换,因此这里以及后面的文章也统一称DTFT为傅里叶变换)被定义为 $X(e^{j\ome ...

  6. 了解AutoCAD对象层次结构 —— 2 ——文档

    再次想象另外一个场景:启动AutoCAD程序后,您新建了两个.dwg文件,也就是说创建了两个文档(Document)对象.将窗口进行层叠,您看到的窗口应该与下图类似: 图 4‑3 如何访问这些文档呢? ...

  7. 下拉列表模仿placeholder效果

    模仿placeholder效果 <select id="IsTop"> <option value="" disabled selected& ...

  8. java excel Workbook API

    此文摘自:http://blog.sina.com.cn/zenyunhai 1. int getNumberOfSheets() 获得工作薄(Workbook)中工作表(Sheet)的个数,示例: ...

  9. 洛谷P1402 酒店之王

    传送门:>Here< 题意:有N个人去酒店,酒店共有P个房间,Q道菜.已知每个人喜欢特定的几个房间和几道菜,一个人是满意的当且仅当住了喜欢的房间,吃了喜欢的菜(一个人只能选一个房间一道菜) ...

  10. Hdoj 2191.悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 题解

    Problem Description 急!灾区的食物依然短缺! 为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品 ...