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 年,人类进入了宇宙纪元. ...
随机推荐
- NotBacon
What's It Do? The application consists of two components: A Custom Vision Service project that allow ...
- Windows Server 2012 Hyper-V 快照
快照 Hyper-V 可提供擷取執行中虛擬機器快照的能力,因此可輕易地回復至前一狀態,對於測試環境相當有幫助. 快照的功用雖然很不錯,不過每次建立快照時都是會消耗相當的硬碟資源,尤其目前的快照點和上一 ...
- python基础数据类型—int、bool、字符串的常用方法
1.int int为整型数据,主要用于计算和类型转化(将字符串转为数字) 常用方法 #bit_length()当用二进制表示数字时所用最少位数,如下十进制数12用二进制表示是1100(bin),所以# ...
- JSON 解析 (三)—— FastJSON与Jackson比较
一.方便性与性能 调用方便性而言: FastJSON提供了大量静态方法,调用简洁方便 Jackson须实例化类,调用相对繁琐,可通过封装成JSON工具类简化调用 性能而言: FastJSON反序列化的 ...
- HDU4035 Maze 【树形DP】【期望DP】
题目分析: 以前一直不会这个方法, 我好菜啊. 转移分为三个部分,一个是直接成功,一个是转移到E1,还有一个是转移到自己周围的一圈儿点. 如果是叶子那么只能转移到父亲,如果不是叶子可以把非叶子的转移代 ...
- Ionic的NavController 和ModalController 的区别
网上也没有找到直接介绍两者区别的文章,以下都是个人感觉 区别 NavController 和 ModalController 都是打开新页面,但是NavController 是直接将页面放入到原有的页 ...
- 【CF833D】Red-Black Cobweb(点分治)
[CF833D]Red-Black Cobweb(点分治) 题面 CF 有一棵树,每条边有一个颜色(黑白)和一个权值,定义一条路径是好的,当且仅当这条路径上所有边的黑白颜色个数a,b满足2min(a, ...
- Luogu P5290 / LOJ3052 【[十二省联考2019]春节十二响】
联考Day2T2...多亏有这题...让我水了85精准翻盘进了A队... 题目大意: 挺简单的就不说了吧...(这怎么简述啊) 题目思路: 看到题的时候想了半天,不知道怎么搞.把样例画到演草纸上之后又 ...
- [ZJOI2005]九数码游戏(BFS+hash)
Solution 这题的话直接上BFS就可以了,因为要输出方案,所以我们要开一个pre数组记录前驱,最后输出就可以了. 对于状态的记录,一般都用哈希来存,但因为这道题比较特殊,它是一个排列,所以我们可 ...
- 【php】php位运算及其高级应用
我们之前学过逻辑与(&&) 条件1 && 条件2 当两边条件同时成立时候返回1 逻辑或(||) 条件1 || 条件2 当两边条件只要有一 ...