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 年,人类进入了宇宙纪元. ...
随机推荐
- Web API 如何请求基于Basic/Bearer 头的方式 C#
public void SetBasicAuthHeader(WebRequest request, String userName, String userPassword) { string au ...
- 思路:controller层:后台如何取值 前端如何给name赋值 例如是id赋值还是自己随意定义
思路:controller层:后台如何取值 前端如何给name赋值 例如是id赋值还是自己随意定义
- 51nod2383
2383 高维部分和 1 秒 131,072 KB 80 分 5 级题 输入一个长度为n的数组a[i],下标从0开始(0到n-1)保证n是2的整数次幂,对于每个i (0 <= i < ...
- Spring IOC注入接口多实现解决
前期面试的时候被面试官问到,Spring注入某接口,而接口有多实现,应该如何处理.接口多实现很常见,但在业务逻辑开发中,需要考虑注入某接口的多个实现问题的情况并不多见.当时是一脸懵逼,目前有时间,就做 ...
- ContOS7编译安装python3,配置虚拟环境
Python36编译安装 一,下载python源码包 网址:https://www.python.org/downloads/release/python-367/ # 软件包下载到/opt目录 cd ...
- 洛谷P1395 会议 题解
$题目$ 为什么这个题会有图论的标签啊,虽然图论也包括找树的重心,可是这很容易让人联想到最短路,但不得不说,这是一个典型的找树的重心模板题. 树的重心是什么? 找到一个点,其所有的子树中最大的子树节点 ...
- [洛谷P2627] 修剪草坪
传送门:>Here< 题意:不能有连续超过$k$个奶牛的一段,求最大的和 思路分析 Dp还是容易看出来的. 我的第一感觉是一维,$f[i]$表示前i头奶牛的最大效率.其实这也是可以解的,具 ...
- Mac 部分软件介绍
1.Pickle可帮你轻松的安装 PHP 扩展,支持所有平台.基于 Composer(PHP的依赖管理器)开发.-----------扩展安装 2.composer parallel install ...
- STL的相关知识
STL简介: STL(Standard Template Library,标准模版库)以模板类和模版函数的形式为程序员提供了各种数据结构和算法的实现,程序员通过利用STL,可以在代码空间.执行时间和编 ...
- Anaconda For Linux (附C#交互式编程的引入)
汇总系列:https://www.cnblogs.com/dunitian/p/4822808.html#ai Jupyter美化: https://www.cnblogs.com/dotnetcra ...