洛谷P2463 [SDOI2008]Sandy的卡片(后缀数组SA + 差分 + 二分答案)
题目链接:https://www.luogu.org/problem/P2463
【题意】
求出N个串中都出现的相同子串的最长长度,相同子串的定义如题:所有元素加上一个数变成另一个,则这两个串相同,可以很简单的得出,差分后的串相同即相同。
【思路】
首先肯定是要对N个串分别进行差分,然后将N个串合并成一个串,首尾相接即可,但要标记那些数属于哪一个Mi(后边要进行check),这里呢要注意,记得将串分隔开来,
不然会WA,这里我用的分隔方法是在串之间加0,合并完成后,题目就可变成求最长的不重叠的重复N次的最长子串长度。因为如果长度为k的串出现了N次,那么他的前缀
也一定出现了N次,所以此题满足单调性,可以进行二分答案。
【check方法】
找到一段排名连续的[l, r]都满足height[i]>=mid( l<i<=r )的连续的区间,对该区间[l, r]进行处理,判断所有的sa[i]( l<=i<=r )的所属Mi,如果有N个不同的Mi即满足条件,返回true,
反之返回false。
上代码
#include <bits/stdc++.h>
using namespace std; const int maxn = 1e6 + ;
int n, t, M, b[maxn], num[], a[maxn];
int sa[maxn], x[maxn], c[maxn], y[maxn], rk[maxn], height[maxn];
bool vis[maxn];
inline void get_sa(){
int m = ;
for( int i=; i<=n; i++ ) ++c[x[i]=a[i]];
for( int i=; i<=m; i++ ) c[i] += c[i-];
for( int i=n; i; i-- ) sa[c[x[i]]--] = i;
for( int k=; k<=n; k<<= ){
int now = ;
for( int i=n-k+; i<=n; i++ ) y[++now] = i;
for( int i=; i<=n; i++ ) if(sa[i]>k) y[++now] = sa[i]-k;
for( int i=; i<=m; i++ ) c[i] = ;
for( int i=; i<=n; i++ ) ++c[x[i]];
for( int i=; i<=m; i++ ) c[i] += c[i-];
for( int i=n; i; i-- ) sa[c[x[y[i]]]--] = y[i], y[i]=;
swap(x, y);
x[sa[]] = now = ;
for( int i=; i<=n; i++ )
x[sa[i]] = (y[sa[i]]==y[sa[i-]] && y[sa[i]+k]==y[sa[i-]+k]) ? now : ++now;
if( now>=n ) return ;
m = now;
}
} inline void get_height(){
int k = ;
for( int i=; i<=n; i++ ) rk[sa[i]] = i;
for( int i=; i<=n; i++ ){
if( rk[i]== ) continue;
if( k ) k--;
int j = sa[rk[i]-];
while( j+k<=n && i+k<=n && a[j+k]==a[i+k] ) k++;
height[rk[i]] = k;
}
} inline bool check1( int l, int r ){
if( r-l+<t ) return ; //!!!!!!!r-l+1<t 不是r-l+1<n
int tmp = ;
memset( vis, , sizeof(vis) );
for( int i=l; i<=r; i++ )
if( !vis[b[sa[i]]] ){
tmp ++;
vis[b[sa[i]]] = ;
}
return tmp == t;
} inline bool check( int x ){
int l=, r=;
while( l<=n ){
while( height[r+]>=x ) r++;
if( check1(l, r) ) return ;
l = r+; r = l;
}
return ;
} int main(){
freopen("in.txt", "r", stdin);
scanf("%d", &t);
int len = ;
for( int i=; i<=t; i++ ){
scanf("%d", &M);
for( int j=; j<M; j++ ) scanf("%d", &num[j]);
for( int j=; j<M; j++ ){
a[++n] = num[j]-num[j-]; //进行差分
b[n] = i;
}
a[++n] = ; //分隔不同的串
b[n] = i;
}
// for( int i=1; i<=n; i++ ) cout << a[i] << endl;
get_sa();
get_height();
// for( int i=1; i<=n; i++ ) cout << height[i] <<endl;
int l=, r=n;
int ans=;
while( l<=r ){
int mid = l+r>>;
if( check(mid) ) ans = mid, l=mid+;
else r = mid-;
}
printf("%d\n", ans+); return ;
}
洛谷P2463 [SDOI2008]Sandy的卡片(后缀数组SA + 差分 + 二分答案)的更多相关文章
- 洛谷 P2463 [SDOI2008]Sandy的卡片 解题报告
P2463 [SDOI2008]Sandy的卡片 题意 给\(n(\le 1000)\)串,定义两个串相等为"长度相同,且一个串每个数加某个数与另一个串完全相同",求所有串的最长公 ...
- [洛谷P2463][SDOI2008]Sandy的卡片
题目大意:有$n$个字符串,求这$n$个字符串中最长的相似公共字串,相似的定义是加上一个数后相同 题解:差分,建广义后缀自动机,然后求出每个点在多少个字符串中出现过,若在$n$个中都出现,就更新答案 ...
- 【BZOJ4698】Sdoi2008 Sandy的卡片 后缀数组+RMQ
[BZOJ4698]Sdoi2008 Sandy的卡片 Description Sandy和Sue的热衷于收集干脆面中的卡片.然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡 ...
- 【bzoj4698】[Sdoi2008] Sandy的卡片 后缀数组
题目描述 Sandy和Sue的热衷于收集干脆面中的卡片.然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡片兑换超炫的人物模型.每一张卡片都由一些数字进行标记,第i张卡片的序列 ...
- BZOJ 4698: Sdoi2008 Sandy的卡片 后缀数组 + RMQ + 查分
题目描述 Sandy和Sue的热衷于收集干脆面中的卡片. 然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡片兑换超炫的人物模型. 每一张卡片都由一些数字进行标记,第i张卡片的 ...
- SDOI2008 Sandy的卡片( 后缀数组 )
求出后缀数组, 然后二分答案, 对height数组分组检验答案. 时间复杂度O(|S| log|S|) ------------------------------------------------ ...
- BZOJ4698: Sdoi2008 Sandy的卡片(后缀数组 二分)
题意 题目链接 Sol 不要问我为什么发两篇blog,就是为了骗访问量 后缀数组的也比较好想,先把所有位置差分,然后在height数组中二分就行了 数据好水啊 // luogu-judger-enab ...
- 洛咕 P2463 [SDOI2008]Sandy的卡片
哈希水过. 首先这是一段delta相同的序列,按照套路差分一下,b[i]=a[i]-a[i-1],然后就是这些序列的最长公共子段 由于数据范围很小,就可以二分,枚举第一个序列的子段然后每个子序列暴力c ...
- BZOJ 4698: Sdoi2008 Sandy的卡片(后缀数组+差分+二分答案)
传送门 解题思路 看到一个子串加一个数字到另一个子串,自然可以想到差分.然后要把所有串都拼起来,求出\(height\)数组后可以二分答案来做,每次二分一个答案后统计一下连续的\(height> ...
随机推荐
- Zabbix设置邮件报警
邮件报警 概述当监控项收集了数据后,触发器会根据异常状态触发报警.根据一些报警机制,它也会通知我们一些重要的事件,而不需要我们直接在Zabbix前端进行查看.这就是通知(Notifications)的 ...
- MySQL实战45讲学习笔记:第十二讲
一.引子 平时的工作中,不知道你有没有遇到过这样的场景,一条 SQL 语句,正常执行的时候特别快,但是有时也不知道怎么回事,它就会变得特别慢,并且这样的场景很难复现,它不只随机,而且持续时间还很短. ...
- 练习题 vue_01:
目录 练习题: vue_01 点击事件控制标签颜色: 点击次数控制标签的样式: 周期性实现标签的旋转变色: 每日一题: http协议,https与http的区别: 前端页面布局的方式 框架内orm的功 ...
- 检查hdfs块的块-fsck
hadoop集群运行过程中,上下节点是常有的事情,如果下架节点,hdfs存储的块肯定会受到影响. 如何查看当前的hdfs的块的状态 hadoop1.x时候的命令,hadoop2.x也可使用: hado ...
- 【转】Visual Studio Code(VS code)你们都在用吗?或许你们需要看一下这篇博文
写在前面 在前端开发中,有一个非常好用的工具,Visual Studio Code,简称VS code. 都不用我安利VS code,大家就会乖乖的去用,无数个大言不惭的攻城狮,都被VS code比德 ...
- 关于 Visual Studio 2017 ,或2019 ,Installer 没检测到已安装的程序.以及C++ 创建项目失败
解决方法: 首先, 把 本机 的Installer.exe 卸载了. 2 , 重新下载 Installer.exe 打开后发现 ,又重新检测到 VS 2019 ,或2017了
- 我是如何一步步编码完成万仓网ERP系统的(三)登录
https://www.cnblogs.com/smh188/p/11533668.html(我是如何一步步编码完成万仓网ERP系统的(一)系统架构) https://www.cnblogs.com/ ...
- 在ASP.NET MVC中创建自定义模块
创建模块 module是实现了System.Web.IHttpModule接口的类.该接口定义了两个方法: Init:当模块初始化时被调用,传入的参数为HttpApplication对象,用于注册请求 ...
- javascript(五)表达式
表达式 (expression) JavaScript中的一个短语, JavaScript解释器会将其计算(evaluate) 出一 个结果.程序中的常量是最简单的一类表达式.变量名也是一种简单的表达 ...
- JS基石之-----数组转换为树结构函数
我们常常在做后台管理系统的时候 需要对数据进行组装成一个树装结构,这里特地将此方法进行封装: let data = [ { id: , text: }, { id: , text: }, { id: ...