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

--------------------------------------------------------------------------------

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
const int maxn = 1009;
const int maxN = 1000009;
 
inline int read() {
char c = getchar();
for(; !isdigit(c); c = getchar());
int ret = 0;
for(; isdigit(c); c = getchar())
ret = ret * 10 + c - '0';
return ret;
}
 
bool vis[maxn];
int str[maxn][maxn], len[maxn], n, Top;
int S[maxN], Id[maxN], stk[maxN], N;
int cnt[maxN], Sa[maxN], Height[maxN], Rank[maxN];
 
void Build(int m) {
int *x = Height, *y = Rank;
for(int i = 0; i < m; i++) cnt[i] = 0;
for(int i = 0; i < N; i++) cnt[x[i] = S[i]]++;
for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1];
for(int i = N; i--; ) Sa[--cnt[x[i]]] = i;
for(int k = 1, p = 0; k <= N; k <<= 1, p = 0) {
for(int i = N - k; i < N; i++) y[p++] = i;
for(int i = 0; i < N; i++)
if(Sa[i] >= k) y[p++] = Sa[i] - k;
for(int i = 0; i < m; i++) cnt[i] = 0;
for(int i = 0; i < N; i++) cnt[x[y[i]]]++;
for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1];
for(int i = N; i--; ) Sa[--cnt[x[y[i]]]] = y[i];
swap(x, y);
p = 1;
x[Sa[0]] = 0;
for(int i = 1; i < N; i++) {
if(y[Sa[i]] != y[Sa[i - 1]] || y[Sa[i] + k] != y[Sa[i - 1] + k]) p++;
x[Sa[i]] = p - 1;
}
if(p >= N) break;
m = p;
}
for(int i = 0; i < N; i++) Rank[Sa[i]] = i;
Height[0] = 0;
for(int i = 0, h = 0; i < N; i++) if(Rank[i]) {
if(h) h--;
while(S[i + h] == S[Sa[Rank[i] - 1] + h]) h++;
Height[Rank[i]] = h;
}
}
 
void Init() {
int mn = 1 << 30, mx = -1 << 30;
n = read();
for(int i = 0; i < n; i++) {
len[i] = read();
for(int j = 0; j < len[i]; j++) str[i][j] = read();
for(int j = len[i]; --j; ) {
str[i][j] -= str[i][j - 1];
mn = min(mn, str[i][j]);
mx = max(mx, str[i][j]);
}
}
N = 0;
for(int i = 0; i < n; i++) {
for(int j = 1; j < len[i]; j++) {
S[N] = str[i][j] - mn + n;
Id[N++] = i;
}
S[N] = n - i - 1;
Id[N++] = n;
}
Build(mx - mn + n + 1);
memset(vis, 0, sizeof vis);
vis[n] = 1;
Top = 0;
}
 
bool chk(int v) {
while(Top) vis[stk[--Top]] = 0;
for(int i = 1; i < N; i++) if(Height[i] >= v) {
if(!vis[Id[Sa[i - 1]]])
vis[stk[Top++] = Id[Sa[i - 1]]] = 1;
if(!vis[Id[Sa[i]]])
vis[stk[Top++] = Id[Sa[i]]] = 1;
if(Top >= n) return true;
} else {
while(Top) vis[stk[--Top]] = 0;
}
return false;
}
 
void Work() {
int l = 1, r = maxN, ans = 0;
while(l <= r) {
int m = (l + r) >> 1;
if(chk(m)) {
ans = m, l = m + 1;
}
else
r = m - 1;
}
printf("%d\n", ++ans);
}
 
int main() {
Init();
Work();
return 0;
}

--------------------------------------------------------------------------------

SDOI2008 Sandy的卡片( 后缀数组 )的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. LG2463/BZOJ4698 「SDOI2008」Sandy的卡片 后缀数组

    问题描述 LG2463 BZOJ4698 题解 看到\(n\)个数串,一开始不太好处理,可以很容易想到把这\(n\)个数串连到一起,形成一个大串,但是每个串之间不容易处理. 经过思考,想到在每个串中间 ...

随机推荐

  1. B/S状态(同步)AJAX技术(异步)

    同步(Synchronization).它是最常见的click-refresh状态,或提交一个表单,然后整个页面被刷新. 异步(Asynchrony).当前非常热的AJAX就是典型样例,提交请求返回对 ...

  2. datagrid指定行合并导出

    导出代码: public void GridViewToExcel(GridView ctrl, string FileType, string FileName) { HttpContext.Cur ...

  3. 《Microsoft SQL Server企业级平台管理实践》笔记

    - 页是 SQL Server 中数据存储的基本单位,大小为 8KB. - 区是空间管理的基本单位,8个物理上连续的页的集合(64KB). - 页的类型包括: 1. Data 2. Index 3. ...

  4. Django学习笔记(一)

    之前没有接触过django,甚至python也是最近才刚刚着手学习,可以说是零基础.要学习一门新技术,官方文档自然是首选的入门教程.开发环境:python2.7+django1.7+win 1.首先, ...

  5. Linux 常用命令学习

    sed 大法: cat file | sed 's/string/replace_str/' file 按大小分割文件 split -b 100m filename 设置vi不自动转换tab: set ...

  6. & 和 && 区别

    java中&和&&的区别,&和&&虽然都是逻辑运算符,都是判断两边为真,则语句成立,但是在运行的时候,还是有差别的,下面举例来说明. java中& ...

  7. OpenCV系列--摄像头控制的简单代码

    操作系统:windows xp 开发工具:VS2008 opencv版本:2.1.0 依赖库:OpenCV2.1\lib\highgui.lib #include "cv.h" # ...

  8. leetcode first bad version python

    # The isBadVersion API is already defined for you. # @param version, an integer # @return a bool # d ...

  9. windows命令行模式下无法打开python程序解决方法

    今天刚开始学Python,首先编写一个简单地hello world程序,想在命令行模式运行,结果出现下面: 经过一番思考,发现用cd命令可以解决这件事,看下图: 这样就解决了.

  10. QT显示GIF图片

    在QT中要显示GIF图片,不能通过单单的添加部件来完成. 还需要手动的编写程序. 工具:QT Creator 新建一个工程,我们先在designer中,添加一个QLabel部件. 如下图: 将QLab ...