题目链接: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 + 差分 + 二分答案)的更多相关文章

  1. 洛谷 P2463 [SDOI2008]Sandy的卡片 解题报告

    P2463 [SDOI2008]Sandy的卡片 题意 给\(n(\le 1000)\)串,定义两个串相等为"长度相同,且一个串每个数加某个数与另一个串完全相同",求所有串的最长公 ...

  2. [洛谷P2463][SDOI2008]Sandy的卡片

    题目大意:有$n$个字符串,求这$n$个字符串中最长的相似公共字串,相似的定义是加上一个数后相同 题解:差分,建广义后缀自动机,然后求出每个点在多少个字符串中出现过,若在$n$个中都出现,就更新答案 ...

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

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

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

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

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

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

  6. SDOI2008 Sandy的卡片( 后缀数组 )

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

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

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

  8. 洛咕 P2463 [SDOI2008]Sandy的卡片

    哈希水过. 首先这是一段delta相同的序列,按照套路差分一下,b[i]=a[i]-a[i-1],然后就是这些序列的最长公共子段 由于数据范围很小,就可以二分,枚举第一个序列的子段然后每个子序列暴力c ...

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

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

随机推荐

  1. 显示隐藏文件.reg

    显示隐藏文件.reg Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Microsoft\Windows\Curren ...

  2. [LeetCode] 545. Boundary of Binary Tree 二叉树的边界

    Given a binary tree, return the values of its boundary in anti-clockwise direction starting from roo ...

  3. [LeetCode] 415. Add Strings 字符串相加

    Given two non-negative numbers num1 and num2 represented as string, return the sum of num1 and num2. ...

  4. [LeetCode] 33. Search in Rotated Sorted Array 在旋转有序数组中搜索

    Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...

  5. 阿里云ECS服务器CentOS7.2安装Python2.7.13

    阿里云ECS服务器CentOS7.2安装Python2.7.13 yum中最新的也是Python 2.6.6,只能下载Python 2.7.9的源代码自己编译安装. 操作步骤如下: 检查CentOS7 ...

  6. DNS 服务器无法正常解析时,可以尝试这样!

    DNS 服务器无法正常解析时,可以尝试这样! ========================================================================联通:12 ...

  7. Webpack 4 : ERROR in Entry module not found: Error: Can't resolve './src'

    ERROR in Entry module not found: Error: Can't resolve './src' in 'E:\ASUS\Documents\VSCode files\Web ...

  8. golang学习笔记 ---rand

    在Golang中,有两个包提供了rand,分别为 "math/rand" 和 "crypto/rand",  对应两种应用场景. "math/rand ...

  9. kafka在zookeeper创建使用了哪些znode节点?

    我们都知道kafka利用zookeeper做分布式管理,具体创建使用了哪些znode节点呢? 答案均在源码的ZkData.scala文件中,具体路径如下: https://github.com/apa ...

  10. asp.net webapi 随笔

    第一次写博客,文笔有限,记录下学习的过程 话不多说,直接开干 首先用vs2017建立一个空网站项目,然后只勾选api 项目建立后,如下结构 其中WebApiConfig类配置了路由相关信息 publi ...