【bzoj4698】[Sdoi2008] Sandy的卡片 后缀数组
题目描述
输入
输出
样例输入
2
2 1 2
3 4 5 9
样例输出
2
题解
后缀数组
由于每组数共同加上一个数,它们的差值不变,所以可以把每组数作差,保存到r中。
然后就是求n个字符串的最长公共字串。
把这些串依次连接起来,放到同一个字符串中,中间用从未出现过的数字隔开(这里使用1000)
然后倍增求出height。
二分答案,若答案合法,则一定有连续的height>mid,且它们属于不同的字符串。
据此写出judge函数,这里我用到了一个栈,均摊时间复杂度为O(n)。
求的是差值,问的是个数,答案别忘了+1。
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 1000005
using namespace std;
int ws[N] , wv[N] , wa[N] , wb[N] , sa[N] , r[N] , rank[N] , height[N] , bl[N] , n , a[N] , m , vis[N] , k , sta[N] , top;
char str[N];
void da()
{
int i , j , p , *x = wa , *y = wb , *t;
for(i = 0 ; i < m ; i ++ ) ws[i] = 0;
for(i = 0 ; i < n ; i ++ ) ws[x[i] = r[i]] ++ ;
for(i = 1 ; i < m ; i ++ ) ws[i] += ws[i - 1];
for(i = n - 1 ; i >= 0 ; i -- ) sa[--ws[x[i]]] = i;
for(p = j = 1 ; p < n ; j <<= 1 , m = p)
{
for(p = 0 , i = n - j ; i < n ; i ++ ) y[p ++ ] = i;
for(i = 0 ; i < n ; i ++ ) if(sa[i] - j >= 0) y[p ++ ] = sa[i] - j;
for(i = 0 ; i < n ; i ++ ) wv[i] = x[y[i]];
for(i = 0 ; i < m ; i ++ ) ws[i] = 0;
for(i = 0 ; i < n ; i ++ ) ws[wv[i]] ++ ;
for(i = 1 ; i < m ; i ++ ) ws[i] += ws[i - 1];
for(i = n - 1 ; i >= 0 ; i -- ) sa[--ws[wv[i]]] = y[i];
for(t = x , x = y , y = t , x[sa[0]] = 0 , p = i = 1 ; i < n ; i ++ )
{
if(y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + j] == y[sa[i] + j])
x[sa[i]] = p - 1;
else
x[sa[i]] = p ++ ;
}
}
for(i = 1 ; i < n ; i ++ ) rank[sa[i]] = i;
for(p = i = 0 ; i < n - 1 ; height[rank[i ++ ]] = p)
for(p ? p -- : 0 , j = sa[rank[i] - 1] ; r[i + p] == r[j + p] ; p ++ );
}
bool judge(int mid)
{
int i , num = 0;
for(i = 0 ; i < k ; i ++ ) vis[i] = 0;
top = 0;
for(i = 2 ; i <= n - 1 ; i ++ )
{
if(height[i] >= mid)
{
if(!vis[bl[sa[i - 1]]]) vis[bl[sa[i - 1]]] = 1 , num ++ , sta[++top] = bl[sa[i - 1]];
if(!vis[bl[sa[i]]]) vis[bl[sa[i]]] = 1 , num ++ , sta[++top] = bl[sa[i]];
if(num == k) return 1;
}
else if(num > 0)
{
num = 0;
while(top) vis[sta[top -- ]] = 0;
}
}
return 0;
}
int main()
{
int i , j , p , le = 0 , ri = 0x7fffff , mi , ans = 0 , minn = 0x7fffffff;
scanf("%d" , &k);
for(i = 0 ; i < k ; i ++ )
{
scanf("%d" , &p);
ri = min(ri , p - 1);
for(j = 0 ; j < p ; j ++ )
scanf("%d" , &a[j]);
for(j = 0 ; j < p - 1 ; j ++ )
{
bl[n] = i;
r[n] = a[j + 1] - a[j];
minn = min(minn , r[n ++ ]);
}
r[n ++ ] = 1000;
}
for(i = 0 ; i < n ; i ++ ) r[i] -= minn - 1 , m = max(m , r[i] + 1);
n ++ ;
da();
while(le <= ri)
{
mi = (le + ri) >> 1;
if(judge(mi))
{
ans = mi;
le = mi + 1;
}
else
{
ri = mi - 1;
}
}
printf("%d\n" , ans + 1);
return 0;
}
【bzoj4698】[Sdoi2008] Sandy的卡片 后缀数组的更多相关文章
- BZOJ4698: Sdoi2008 Sandy的卡片(后缀数组 二分)
题意 题目链接 Sol 不要问我为什么发两篇blog,就是为了骗访问量 后缀数组的也比较好想,先把所有位置差分,然后在height数组中二分就行了 数据好水啊 // luogu-judger-enab ...
- 【BZOJ4698】Sdoi2008 Sandy的卡片 后缀数组+RMQ
[BZOJ4698]Sdoi2008 Sandy的卡片 Description Sandy和Sue的热衷于收集干脆面中的卡片.然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡 ...
- 【BZOJ-4698】Sandy的卡片 后缀数组
4698: Sdoi2008 Sandy的卡片 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 140 Solved: 55[Submit][Stat ...
- BZOJ 4698: Sdoi2008 Sandy的卡片 后缀数组 + RMQ + 查分
题目描述 Sandy和Sue的热衷于收集干脆面中的卡片. 然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡片兑换超炫的人物模型. 每一张卡片都由一些数字进行标记,第i张卡片的 ...
- SDOI2008 Sandy的卡片( 后缀数组 )
求出后缀数组, 然后二分答案, 对height数组分组检验答案. 时间复杂度O(|S| log|S|) ------------------------------------------------ ...
- BZOJ 4698: Sdoi2008 Sandy的卡片(后缀数组+差分+二分答案)
传送门 解题思路 看到一个子串加一个数字到另一个子串,自然可以想到差分.然后要把所有串都拼起来,求出\(height\)数组后可以二分答案来做,每次二分一个答案后统计一下连续的\(height> ...
- [BZOJ4698][SDOI2008]Sandy的卡片(后缀自动机)
差分之后就是求多串LCS. 对其中一个串建SAM,然后把其它串放在上面跑. 对SAM上的每个状态都用f[x]记录这个状态与当前串的最长匹配长度,res[x]是对每次的f[x]取最小值.答案就是res[ ...
- 洛谷P2463 [SDOI2008]Sandy的卡片(后缀数组SA + 差分 + 二分答案)
题目链接:https://www.luogu.org/problem/P2463 [题意] 求出N个串中都出现的相同子串的最长长度,相同子串的定义如题:所有元素加上一个数变成另一个,则这两个串相同,可 ...
- BZOJ 4698: Sdoi2008 Sandy的卡片 [后缀自动机]
4698: Sdoi2008 Sandy的卡片 题意:差分后就是多个串LCS SAM+map大法好 模板打错 智力-2 #include <iostream> #include <c ...
随机推荐
- substr是不安全的
今天遇到一个问题,数据库中保存的内容通过php在页面无法显示,如果将内容换行或加个空格或者随便加点其他内容就能正常显示. 非常的诡异,显示的内容是通过截取得到的.代码非常简单 substr($pMar ...
- 阅读笔记《JavaScript语言精粹》
阅读笔记<JavaScript语言精粹> 对象 1.检索属性 使用[]和. 2.引用传递 JavaScript的简单数据类型包括数字.字符串.布尔值.null值和undefined值.其它 ...
- 二 Hive分桶
二.Hive分桶 1.创建分桶表 create table t_buck (id string ,name string) clustered by (id) //根据id分桶 sorted by ( ...
- Awesome Flask
Awesome Flask A curated list of awesome Flask resources and plugins Awesome Flask Framework Admin i ...
- javaweb(四)——Http协议(请求头,响应头详解)
一.什么是HTTP协议 HTTP是hypertext transfer protocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的 ...
- Python输入数据类型判断正确与否的函数大全(非常全)
对于python输入数据类型判断正确与否的函数大致有三类: (1)type(),它的作用直接可以判断出数据的类型 (2)isinstance(),它可以判断任何一个数据与相应的数据类型是否一致,比 ...
- NO.01---今天聊聊Vuex的简单入门
作为一款个人认为非常牛x的框架,个人使用起来得心应手,所以近期就记录一下这款框架吧. 首先说一说 Vuex 是什么? 官方给出的解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它 ...
- 【system.file】使用说明
对象:system.file 说明:提供一系列针对文件操作的方法. 注意:参数中的filePath 均为相对网站根目录路径 目录: 方法 返回 说明 system.file.exists(filePa ...
- 如何处理 jQuery $(window).resize() 中的方法被多次执行的小问题
引言: 估计很多同志们在编写浏览器resize()的方法时,都会遇到这样的情况: 当拖动浏览器的边角时,页面中的一些效果随浏览器大小的改变而触发,这一过程开始到结束,resize() 中的方法被执行了 ...
- Java算法2
实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 分析:若从前向后遍历的话,那Happy后面 ...