【BZOJ4698】Sdoi2008 Sandy的卡片 后缀数组+RMQ
【BZOJ4698】Sdoi2008 Sandy的卡片
Description
Input
Output
Sample Input
2 1 2
3 4 5 9
Sample Output
题解:本题让我们求的是变化趋势相同的子串,那么我们直接求出每个数串相邻两项的差,然后用这个差来求最长公共子串就行了。当然,这些差可能会有负值,那就集体减去最小值-1(防止出现0)就行了。先把这些串全部连接起来,中间用极大值隔开,求出sa和height。然后再height数组上维护这样一个区间,使得这个区间中的后缀在每个数串中都出现过,并且区间长度尽可能短,然后从左向右平移这个区间,用RMQ维护区间中最小的height,答案就是这个最大的最小值+1。当然这题也可以二分答案来做。
因为RMQ写错竟然调了一天,感觉我有几年没写RMQ了。
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn=200010;
int minn,maxx;
int r[maxn],ra[maxn],rb[maxn],st[maxn],sa[maxn],rank[maxn],h[maxn];
int N,M[maxn],sm[maxn],bel[maxn],n,m,v[maxn];
int s[maxn],sum,ans;
int dp[maxn][20],Log[maxn];
void work()
{
int i,j,k,*x=ra,*y=rb,p;
for(i=0;i<n;i++) st[x[i]=r[i]]++;
for(i=1;i<m;i++) st[i]+=st[i-1];
for(i=n-1;i>=0;i--) sa[--st[x[i]]]=i;
for(j=p=1;p<n;j<<=1,m=p)
{
for(i=n-j,p=0;i<n;i++) y[p++]=i;
for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
for(i=0;i<m;i++) st[i]=0;
for(i=0;i<n;i++) st[x[y[i]]]++;
for(i=1;i<m;i++) st[i]+=st[i-1];
for(i=n-1;i>=0;i--) sa[--st[x[y[i]]]]=y[i];
for(swap(x,y),i=p=1,x[sa[0]]=0;i<n;i++)
x[sa[i]]=(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+j]==y[sa[i]+j])?p-1:p++;
}
for(i=1;i<n;i++) rank[sa[i]]=i;
for(i=k=0;i<n-1;h[rank[i++]]=k)
for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
}
void rmq()
{
int i,j;
for(i=2;i<n;i++) Log[i]=Log[i>>1]+1;
for(i=1;i<n;i++) dp[i][0]=h[i];
for(j=1;(1<<j)<n;j++)
for(i=1;i+(1<<j)-1<n;i++)
dp[i][j]=min(dp[i][j-1],dp[i+(1<<j-1)][j-1]);
}
int getmin(int a,int b)
{
int k=Log[b-a+1];
return min(dp[a][k],dp[b-(1<<k)+1][k]);
}
int main()
{
scanf("%d",&N);
int i,j,now=0;
sm[0]=-1;
for(i=1;i<=N;i++)
{
scanf("%d",&M[i]);
sm[i]=sm[i-1]+M[i];
scanf("%d",&v[1]);
for(j=2;j<=M[i];j++)
{
bel[now]=i;
scanf("%d",&v[j]);
r[now]=v[j]-v[j-1];
maxx=max(maxx,r[now]);
minn=min(minn,r[now++]);
}
now++;
}
for(i=0;i<sm[N];i++) r[i]-=minn-1;
r[sm[N]]=0;
m=maxx-minn+1;
for(i=1;i<N;i++) r[sm[i]]=m+1;
n=sm[N]+1,m+=2;
work();
rmq();
for(i=1;i<n;i++)
{
if(!s[bel[sa[i]]])
{
if(sum==N-1) break;
sum++;
}
s[bel[sa[i]]]++;
}
now=1;
for(;i<n;i++)
{
if(!bel[sa[i]]) break;
s[bel[sa[i]]]++;
while(s[bel[sa[now]]]>1) s[bel[sa[now++]]]--;
ans=max(ans,getmin(now+1,i));
}
printf("%d",ans+1);
return 0;
}
【BZOJ4698】Sdoi2008 Sandy的卡片 后缀数组+RMQ的更多相关文章
- BZOJ 4698: Sdoi2008 Sandy的卡片 后缀数组 + RMQ + 查分
题目描述 Sandy和Sue的热衷于收集干脆面中的卡片. 然而,Sue收集卡片是因为卡片上漂亮的人物形象,而Sandy则是为了积攒卡片兑换超炫的人物模型. 每一张卡片都由一些数字进行标记,第i张卡片的 ...
- BZOJ4698: Sdoi2008 Sandy的卡片(后缀数组 二分)
题意 题目链接 Sol 不要问我为什么发两篇blog,就是为了骗访问量 后缀数组的也比较好想,先把所有位置差分,然后在height数组中二分就行了 数据好水啊 // luogu-judger-enab ...
- 【BZOJ-4698】Sandy的卡片 后缀数组
4698: Sdoi2008 Sandy的卡片 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 140 Solved: 55[Submit][Stat ...
- 【bzoj4698】[Sdoi2008] Sandy的卡片 后缀数组
题目描述 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 ...
随机推荐
- iOS边练边学--UIScrollView和xib文件实现简单分页+定时器初使用
一.xib文件构成 二.自定义控件类(xib文件与自定义控件类的文件名字相同,并且将xib文件中父类控件的类名改成自定义控件类的名称) ***********自定义控件类需要的属性********** ...
- WPF教程二:布局之StackPanel面板
应用程序界面设计中,合理的元素布局至关重要,它可以方便用户使用,并将信息清晰合理地展现给用户.WPF提供了一套功能强大的工具-面板(Panel),来控制用户界面的布局.你可以使用这些面板控件来排布元素 ...
- zebra/quagga
参考:http://blog.chinaunix.net/uid-25513153-id-212328.html 一.zebra安装 .编译安装 vim ./lib/zebra.h + 增加: #if ...
- am335x phy led problem
问题描述 连接网线的情况下,每次进行软件"reboot",网口的LINK LED能够正常的熄灭,而ACTIVE LED却是亮的. reboot重启之后,LINK的灯正常变亮,而AC ...
- JDK中的序列化和反序列化
题外话:诸事缠身,不知不觉距离上一篇就将近一个月了,读书不易,学习不易,唯有坚持. 写来写去始终不满意,索性贴一个比较好的文章吧! 参考: [Java基础]序列化与反序列化深入分析
- php -- 读取文本文件内容
php读取文件内容的三种方法: //**************第一种读取方式***************************** 代码如下: header("content- ...
- 小知识(class文件查看jdk版本,beyond,could not find setter)
最近几天工作当中遇到了一些问题,所以记录下来. 1.如何查看class文件的sdk版本 2.beyond compare比对文件 3.Could not find setter for native_ ...
- error C2275: 'SOCKET' : illegal use of this type as an expression
在VC中编译xxx.c文件出现错误error C2275 illegal use of this type as an expression 问题在于C99之前要求所有的声明必须放在函数块的起始部分, ...
- React 生态系统:从小白到大神
http://mp.weixin.qq.com/s/Epx46lznpnvgrIsbmAIZBA
- web.xml 中的listener、filter、servlet 加载顺序及其【配置详解】
在项目中总会遇到一些关于加载的优先级问题,近期也同样遇到过类似的,所以自己查找资料总结了下,下面有些是转载其他人的,毕竟人家写的不错,自己也就不重复造轮子了,只是略加点了自己的修饰. 首先可以肯定的是 ...