Sandy的卡片 bzoj-4698 Sdoi-2008

题目大意题目链接

注释:略。


想法

这个题跟一个Usaco的题特别像。我们把这些串差分

现在我们要求的就是公共子串且出现次数不少于$k$的最长长度。

紧接着把这$n$新串拼一起建立后缀数组。

两种做法:

第一种是二分。我们直接二分答案然后暴力扫验证,复杂度为$O(nlogn)$。

第二种就是双指针保证当前指针中间是满足条件的最短区间,顺便用单调队列求区间$ht$最小值即可。

Code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 1000050
int r[N],sa[N],wa[N],wb[N],wv[N],rk[N],ht[N],n,Ws[N],cnt,idx[N],H[1050],tot,ans,Q[N],m;
int w[100050];
inline char nc() {static char *p1,*p2,buf[100000]; return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}
int rd() {int x=0; char c=nc(); while(!isdigit(c)) c=nc(); while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=nc(); return x;}
void build_sa()
{
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,i=p=1,x[sa[0]]=0;i<n;i++)
{
if(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+j]==y[sa[i-1]+j]) x[sa[i]]=p-1;
else x[sa[i]]=p++;
}
}
for(i=1;i<n;i++) rk[sa[i]]=i;
for(i=p=0;i<n-1;ht[rk[i++]]=p)
for(p?p--:0,j=sa[rk[i]-1];r[i+p]==r[j+p];p++);
}
int main()
{
int i,j=0;
cnt=rd();
int minn=1<<30,maxx=0;
for(j=1;j<=cnt;j++)
{
int lim;
lim=rd();
for(i=0;i<lim;i++) w[i]=rd();
for(i=1;i<lim;i++) idx[n]=j,r[n++]=w[i]-w[i-1],minn=min(minn,r[n-1]),maxx=max(maxx,r[n-1]);
n++;
}
m=maxx-minn+1;
for(i=0;i<n;i++)
{
if(idx[i]) r[i]-=minn-1;
else r[i]=m+1;
}
r[n++]=0; m+=2;
build_sa();
int ll=0,rr=0; j=0;
for(i=0;i<n;i++)
{
H[idx[sa[i]]]++; if(H[idx[sa[i]]]==1&&idx[sa[i]]) tot++;
while(ll<rr&&ht[Q[rr-1]]>ht[i]) rr--;
Q[rr++]=i;
if(tot!=cnt) continue;
while(j<i&&tot==cnt)
{
H[idx[sa[j]]]--;
if(H[idx[sa[j]]]==0&&idx[sa[j]]) tot--;
j++;
}
j--; H[idx[sa[j]]]++;
if(H[idx[sa[j]]]==1&&idx[sa[j]]) tot++;
while(ll<rr&&Q[ll]<=j) ll++;
if(tot==cnt)
{
ans=max(ans,ht[Q[ll]]);
}
}
printf("%d\n",ans+1);
return 0;
}

小结:好题好题。一般情况下后缀数组的考点就是在$ht$上搞事情,多注意点儿即可。

[bzoj4698][Sdoi2008]Sandy的卡片_后缀数组_二分/单调队列_双指针的更多相关文章

  1. 【BZOJ4698】Sandy的卡片(后缀数组)

    [BZOJ4698]Sandy的卡片(后缀数组) 题面 讨厌权限题!!! 因为我交不了... 洛谷 题面 做完差之后就是裸的最长公共子串 没了.. 数组往死里开吧... #include<ios ...

  2. 【BZOJ4698】[SDOI2008] Sandy的卡片(后缀数组+二分)

    点此看题面 大致题意: 给你\(N\)个序列,若定义两个相同子串为一个子串内所有数加上一个数后能变成另一个串,求所有序列中的最长相同子串的长度. 简单的转化 首先,我们对题目进行一个简单的转化. 要求 ...

  3. 4698. [SDOI2008]Sandy的卡片【后缀数组】

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

  4. luogu 2463 [SDOI2008]Sandy的卡片 kmp || 后缀数组 n个串的最长公共子串

    题目链接 Description 给出\(n\)个序列.找出这\(n\)个序列的最长相同子串. 在这里,相同定义为:两个子串长度相同且一个串的全部元素加上一个数就会变成另一个串. 思路 参考:hzwe ...

  5. [luoguP2463] [SDOI2008]Sandy的卡片(后缀数组 + st表)

    传送门 很容易想到,题目中的相同是指差分数组相同. 那么可以把差分数组连起来,中间加上一个没有出现过的且字典序小的数 双指针移动,用st表维护height数组中的最小值. 当然用单调队列应该也可以且更 ...

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

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

  7. 洛谷P2463 Sandy的卡片【后缀数组】【二分】

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

  8. BZOJ4698: Sdoi2008 Sandy的卡片(二分 hash)

    题意 题目链接 Sol 用什么后缀数组啊 直接差分之后 二分+hash找最长公共子串就赢了啊... 时间复杂度:\(O(nlogn)\)(不过我写的是两个log..反正也能过) // luogu-ju ...

  9. [BZOJ4698][SDOI2008]Sandy的卡片(后缀自动机)

    差分之后就是求多串LCS. 对其中一个串建SAM,然后把其它串放在上面跑. 对SAM上的每个状态都用f[x]记录这个状态与当前串的最长匹配长度,res[x]是对每次的f[x]取最小值.答案就是res[ ...

随机推荐

  1. jquery readio checked

    今天太鬼火了为这个难问题搜了一下午了到最后还是csdn的朋友给了我正确的答案http://bbs.csdn.net/topics/300162450谢谢这位朋友 // $("#ISOK1&q ...

  2. Myeclipse 6.0代码

    import java.util.*; import java.io.*; public class bbs { private static final String LL = "Deco ...

  3. [POJ1509]Glass Beads 后缀自动机 最小循环串

    题目链接:http://poj.org/problem?id=1509 题目意思就是求循环字符串的最小表示. 我们用字符串S+S建立SAM,然后从root开始走n步,每次尽量选最小的. 由于 SAM ...

  4. php(三)使用PDO链接数据库

    1.启动 mysql数据库,打开图形化控制界面 2.新建一个数据库 3.创建一个数据表 4.给数据表添加数据 id是数字类型的  类型选择int长度 11 username 等其他数据  会是字符串形 ...

  5. iOS Programming UIWebView 2

    iOS Programming  UIWebView 1 Instances of UIWebView render web content. UIWebView可以显示web content. In ...

  6. vue热重载

    依据官网使用 webpack 的 Hot Module Replacement API,Vuex 支持在开发过程中热重载 mutation.module.action 和 getter.你也可以在 B ...

  7. 关于js中使用close方法无法关闭firefox浏览器

    今天遇到一个问题就是在js中使用window.close()方法无法关闭Firefox: 浏览器版本: firefox

  8. 迅为7寸工业平板电脑|人机界面|工业触摸屏|工控机|HMI|工业显示器

    型号:iTOP-HMI070-C 7寸工业平板电脑特点: 1.iTOP-HMI070-C(CAN) 7寸工业触摸屏,CAN总线型触摸屏,配有2组独立的串口和一路CAN总线口: 2.串口都支持各种PLC ...

  9. leetcode_1015. Numbers With Repeated Digits

    https://leetcode.com/problems/numbers-with-repeated-digits/ 与leetcode_357. Count Numbers with Unique ...

  10. codeforces_C. Sequence Transformation

    http://codeforces.com/contest/1059/problem/C 题意: 最初给一个1.2.3.…….n的序列,每次操作先将所有元素的最大公约数加入答案序列,然后在序列中任意删 ...