BZOJ4698 差分 + 二分 + SA
https://www.lydsy.com/JudgeOnline/problem.php?id=4698
题意:求N个字符串中最长的相同字串的长度,相同的定义是:两个子串长度相同且一个串的全部元素加上一个数就会变成另一个串。
这题的难点在于相同的定义,在这样的定义下一般的字符串匹配算法就不适用了。
但是可以通过一个操作,将前后相邻的字符串差分形成一个长度为len - 1的差分串,原来的相同下的定义就转为了差分串的完全相同,证明显然。
在这种情况下,再把字符串全部拼接起来,用特殊字符隔开,然后二分他们的长度去做后缀数组,看有没有相邻的一个区间同时满足长度最大并且包含所有K个字符串。
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = 1e6 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
int str[maxn],id[maxn];
int a[maxn],Height[maxn];
int tax[maxn],tp[maxn],sa[maxn],rak[maxn];
void Qsort(){
for(int i = ; i <= M; i ++) tax[i] = ;
for(int i = ; i <= N ; i ++) tax[rak[i]]++;
for(int i = ; i <= M ; i ++) tax[i] += tax[i - ];
for(int i = N; i >= ; i --) sa[tax[rak[tp[i]]]--] = tp[i];
}
void SA(){
for(int i = ; i <= N; i ++) rak[i] = str[i],tp[i] = i;
Qsort();
for(int w = ,p = ; p < N;w <<= , M = p){
p = ;
for(int i = ; i <= w; i ++) tp[++p] = N - w + i;
for(int i = ; i <= N ; i ++) if(sa[i] > w) tp[++p] = sa[i] - w;
Qsort(); swap(tp,rak);
rak[sa[]] = p = ;
for(int i = ; i <= N ; i ++){
rak[sa[i]] = (tp[sa[i]] == tp[sa[i - ]] && tp[sa[i] + w] == tp[sa[i - ] + w])?p:++p;
}
}
}
void Get_Height(){
int k = ,j;
for(int i = ; i <= N; i ++){
if(k) k --;
int j = sa[rak[i] - ];
while(str[j + k] == str[i + k]) k++;
Height[rak[i]] = k;
}
}
int Stack[maxn];
bool vis[maxn];
bool check(int x){
int top = ;
int num = K;
for(int i = ; i <= K; i ++) vis[i] = ;
for(int i = ; i <= N ; i ++){
if(Height[i] >= x){
if(!vis[id[sa[i]]]){
vis[id[sa[i]]] = ;
Stack[++top] = id[sa[i]];
num--;
}
if(!vis[id[sa[i - ]]]){
vis[id[sa[i - ]]] = ;
Stack[++top] = id[sa[i - ]];
num--;
}
if(!num) return true;
}else{
for(int j = ; j <= top; j ++) vis[Stack[j]] = ;
top = ;
num = K;
}
}
return false;
}
int solve(){
int l = ,r = N - ;
int ans = ;
while(l <= r){
int m = l + r >> ;
if(check(m)){
ans = m;
l = m + ;
}else{
r = m - ;
}
}
return ans + ;
}
int main(){
Sca(K); N = ;
M = ;
int MIN = INF;
for(int i = ; i <= K ; i ++){
int x = read();
a[] = read();
for(int j = ; j <= x; j ++){
a[j] = read();
str[++N] = a[j] - a[j - ];
MIN = min(MIN,a[j] - a[j - ]);
id[N] = i;
}
str[++N] = ++M; id[N] = i;
}
if(MIN <= ){
MIN = -MIN + ;
for(int i = ; i <= N ; i ++) str[i] += MIN;
M += MIN;
}
SA(); Get_Height();
Pri(solve());
return ;
}
BZOJ4698 差分 + 二分 + SA的更多相关文章
- P1083 借教室(差分+二分)
P1083 借教室 第一眼:线段树. 然鹅懒得写. 正解:差分+二分. 显然订单合法的上线可以二分 然后差分数组维护一下.没了. #include<iostream> #include&l ...
- [NOIP2015]运输计划 线段树or差分二分
目录 [NOIP2015]运输计划 链接 思路1 暴力数据结构 思路2 二分树上差分 总的 代码1 代码2 [NOIP2015]运输计划 链接 luogu 好久没写博客了,水一篇波. 思路1 暴力数据 ...
- ZZNU-OJ-2098 : Drink coffee【线段树合并区间或者 差分 + 二分索引树】
: Drink coffee 时间限制: Sec 内存限制: MiB 提交: 答案正确: 提交 状态 讨论区 题目描述 为了在上课时保持清醒,凯伦需要一些咖啡.咖啡爱好者凯伦想知道最佳的温度来冲煮完美 ...
- 洛谷P2463 [SDOI2008]Sandy的卡片(后缀数组SA + 差分 + 二分答案)
题目链接:https://www.luogu.org/problem/P2463 [题意] 求出N个串中都出现的相同子串的最长长度,相同子串的定义如题:所有元素加上一个数变成另一个,则这两个串相同,可 ...
- poj 1743 Musical Theme【二分+SA】
差分,然后二分长度mid,判断是把height按照min不小于mid分组,取最大最小的sa位置看是否>=mid即可,注意差分后最后答案要+1 #include<iostream> # ...
- BZOJ 4698: Sdoi2008 Sandy的卡片(后缀数组+差分+二分答案)
传送门 解题思路 看到一个子串加一个数字到另一个子串,自然可以想到差分.然后要把所有串都拼起来,求出\(height\)数组后可以二分答案来做,每次二分一个答案后统计一下连续的\(height> ...
- NOIP2012借教室[线段树|离线 差分 二分答案]
题目描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要 向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自 ...
- 【BZOJ-4326】运输计划 树链剖分 + 树上差分 + 二分
4326: NOIP2015 运输计划 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 703 Solved: 461[Submit][Status] ...
- [NOIP 2015]运输计划-[树上差分+二分答案]-解题报告
[NOIP 2015]运输计划 题面: A[NOIP2015 Day2]运输计划 时间限制 : 20000 MS 空间限制 : 262144 KB 问题描述 公元 2044 年,人类进入了宇宙纪元. ...
随机推荐
- 前端传递给后端且通过cookie方式,尽量传递id
前端传递给后端且通过cookie方式,尽量传递id
- Nginx split_client模块
一般用户AB测试根据比例调用指定的接口 默认编译进nginx Syntax: split_clients string $variable { ... } Default: — Context: h ...
- YUV格式与RGB格式
YUV420介绍: YUV420格式是指,每个像素都保留一个Y(亮度)分量,而在水平方向上,不是每行都取U和V分量,而是一行只取U分量,则其接着一行就只取V分量,以此重复(即4:2:0, 4:0:2, ...
- 转 Debugging AutoCAD 2017 using Visual Studio 2015
原文地址: http://adndevblog.typepad.com/autocad/2016/05/debugging-autocad-2017-using-visual-studio-2015. ...
- Cent OS安装使用ffmpeg(完整版)
Cent OS安装使用ffmpeg centos作为主流后台linux 系统,ffmpeg作为视频流解析的主力,尤其是ffmpeg配合opencv使用,则是视觉操作的基础 版本: ffmpeg3.1 ...
- ajax 提交Dictionary
ajax向webapi提交Dictionary Script: var data = { "a": 1, "b": 2, "c": &quo ...
- mysql Navicat 连接MySQL 8.0.11 出现2059错误
https://www.cnblogs.com/lifan1998/p/9177731.html 原因 mysql8 之前的版本中加密规则是mysql_native_password,而在mysql8 ...
- HNOI2017 抛硬币 (FakeBeng)
除了队长快跑外最难的题吧. 除了需要写\(exLucas\)之外,还教会了我大量的卡常技巧. 首先\(70\)分就是个直接按题意模拟,易得\(ans=\sum_{j=0}^{b} C_{b}^{j}\ ...
- Hdoj 1548.A strange lift 题解
Problem Description There is a strange lift.The lift can stop can at every floor as you want, and th ...
- 「SCOI2016」妖怪 解题报告
「SCOI2016」妖怪 玄妙...盲猜一个结论,然后过了,事后一证,然后假了,数据真水 首先要最小化 \[ \max_{i=1}^n (1+k)x_i+(1+\frac{1}{k})y_i \] \ ...