题意

有M篇标准作文组成了一个作文库(每篇作文都是一个01的字符串),然后给出N篇作文(自然也是01字符串)。如果一个长度不小于L的串在作文库中出现过,那么它是熟悉的。对于某一篇作文,我们要把它分为若干段,使得熟悉过的字符串长度>=百分之90,我们要求满足这个条件的最小的L。

分析

这个L显然满足二分,然后我们要想怎么判断,对于当前L,这篇作文的熟悉过字符串的最长长度是什么。我们先把作文库建一个广义后缀自动机,然后对于每篇作文很容易可以求出一个len[i]指的是在i位置结束的子串在作文库中出现过的最长长度是多少。然后我们来dp。设f[i]为前缀i的最长熟悉长度。那么f[i]=max(f[i-1],f[j]+i-j+1|(i-L>=j>=len[i]-i))。但是这个dp是要O(n^2)的。但是我们发现,这个dp是单调的,也就是说i如果是从j递推来的,那么i+1 就不可能从j以前递推来。所以这个j我们用单调队列来维护。我们单调队列中存的是根据值f[j]-j单调的j值。

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue> using namespace std;
const int maxn=;
char s[maxn];
struct state{
int len,link;
int next[];
}st[*maxn];
int len[maxn];
int N,M,n;
int last,cur,sz;
void init(){
sz=;
cur=last=;
st[].link=-;
st[].len=;
}
void build_sam(int c){
cur=sz++;
st[cur].len=st[last].len+;
int p;
for(p=last;p!=-&&st[p].next[c]==;p=st[p].link)
st[p].next[c]=cur;
if(p==-)
st[cur].link=;
else{
int q=st[p].next[c];
if(st[q].len==st[p].len+){
st[cur].link=q;
}else{
int clone=sz++;
st[clone].len=st[p].len+;
st[clone].link=st[q].link;
for(int i=;i<;i++)
st[clone].next[i]=st[q].next[i];
for(;p!=-&&st[p].next[c]==q;p=st[p].link)
st[p].next[c]=clone;
st[cur].link=st[q].link=clone;
}
}
last=cur;
}
int f[maxn];
//dp[i]=max(dp[j]+i-j| i-len[i]<=j<=i-L) bool check(int L){
deque<int>q;
for(int i=;i<=n;i++){
f[i]=f[i-];
if(i<L)continue;
while(!q.empty()&&f[q.back()]-q.back()<f[i-L]-i+L)
q.pop_back();
q.push_back(i-L);
while(!q.empty()&&q.front()<i-len[i])
q.pop_front();
if(!q.empty())
f[i]=max(f[i],f[q.front()]+i-q.front());
}
return f[n]*>=n*;
} int main(){
scanf("%d%d",&N,&M);
init();
for(int i=;i<=M;i++){
scanf("%s",s);
n=strlen(s);
for(int j=;j<n;j++){
int c=s[j]-'';
build_sam(c);
}
last=;
}
for(int q=;q<=N;q++){
scanf("%s",s+);
n=strlen(s+);
int u=,Len=;
for(int i=;i<=n;i++){
int c=s[i]-'';
while(u!=-&&st[u].next[c]==){
u=st[u].link;
Len=st[u].len;
}
if(u==-)
u=,Len=;
else{
u=st[u].next[c];
Len++;
}
len[i]=Len;
}
int l=,r=n,ans=;
while(l<=r){
int mid=l+(r-l)/;
if(check(mid)){
ans=mid;
l=mid+;
}else{
r=mid-;
}
}
printf("%d\n",ans);
}
return ;
}

【BZOJ2806】Cheat 【广义后缀自动机+单调队列优化dp+二分】的更多相关文章

  1. BZOJ 2806: [Ctsc2012]Cheat [广义后缀自动机 单调队列优化DP 二分]

    2806: [Ctsc2012]Cheat 题意: 多个主串和多个询问串,每次询问将询问串分成多个连续子串,如果一个子串长度>=L且在主串中出现过就是熟悉的 如果熟悉的字符串长度>=询问串 ...

  2. 【BZOJ2806】【CTSC2012】Cheat - 广义后缀自动机+单调队列优化DP

    题意: Description Input 第一行两个整数N,M表示待检查的作文数量,和小强的标准作文库的行数 接下来M行的01串,表示标准作文库 接下来N行的01串,表示N篇作文 Output N行 ...

  3. bzoj 2806 [Ctsc2012]Cheat——广义后缀自动机+单调队列优化DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2806 只想着怎么用后缀数据结构做,其实应该考虑结合其他算法. 可以二分那个长度 L .设当前 ...

  4. BZOJ 2806 [Ctsc2012]Cheat ——后缀自动机 单调队列优化DP

    先建出广义后缀自动机. 然后跑出文章中每一个位置的最大匹配距离. 然后定义$f[i]$表示匹配到以$i$结尾的串时,最长的匹配距离. 显然可以二分$L$的取值. 然后容易得到$DP$方程 $f[i]= ...

  5. 单调队列优化DP,多重背包

    单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...

  6. bzoj1855: [Scoi2010]股票交易--单调队列优化DP

    单调队列优化DP的模板题 不难列出DP方程: 对于买入的情况 由于dp[i][j]=max{dp[i-w-1][k]+k*Ap[i]-j*Ap[i]} AP[i]*j是固定的,在队列中维护dp[i-w ...

  7. hdu3401:单调队列优化dp

    第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...

  8. Parade(单调队列优化dp)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others)    ...

  9. BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP

    BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...

随机推荐

  1. OMAP4之DSP核(Tesla)软件开发学习(三)使能DSP核

    目标: 1.编译或直接获取DSP映像tesla-dsp.bin. 2.boot并使能DSP核(这个可以看启动打印或者进入/d/remoteproc/omap-rproc.0/参看dsp调试信息).   ...

  2. 如何修改windows系统的host文件

    方法/步骤   首先我们打开我的计算机     然后我们进入C盘的C:\Windows\System32\drivers\etc这个目录下面找到host这个文件   双点击打开,选择计算本打开,这时可 ...

  3. Java中,什么时候用logger.debuge,info,error

    简单的说,就是配合log的等级过滤输出比如,你在开发的时候,要验证一个方法有没有被调用到,为了方便调试,通常会在这个方法开始的时候加一些system.out.但是项目真正发布的时候这些代码通常是要移除 ...

  4. iOS-----使用AddressBookUI管理联系人

    使用AddressBookUI管理联系人 iOS SDK为管理地址簿提供的视图控制器位于AddressBookUI框架内.总结来说,AddressBookUI框架提供了如下特殊的视图控制器. ABPe ...

  5. Ubuntu系统配置apt-get软件更新源

    从别人那摘录的Ubuntu源,测的很好用 # 电子科技大学 (教育网) deb http://ubuntu.uestc.edu.cn/ubuntu/ oneiric main restricted u ...

  6. 去掉PowerDesigner生成SQL脚本中字段名带的引号

    使用PowerDesigner生成数据库建表SQL脚本时,尤其是Oracle数据库时,表名一般会带引号.其实加引号是PL/SQL的规范,数据库会严格按照“”中的名称建表,如果没有“”,会按照ORACL ...

  7. Oracle XE自带数据库创建的过程

    Oracle XE自带数据库如何创建的?XE.sql脚本定义实例究竟是怎样的?阅读下文,您可以找到这些问题的答案. Oracle XE自带数据库是如何创建的呢?这是很多人都提到过的问题,下面就为您详细 ...

  8. Oracle单表去重复(二)

    Oracle单表去重 去重有两层含义,一:是记录完全一样.二:是符合一定条件的认为是重复. 根据表的数量,去重可划分为:单表去重和多表关联去重.   对于去重,一般最容易想到的是用distinct,而 ...

  9. Centos下telnet的安装和配置

    Centos下telnet的安装和配置 首先为Centos配置地址(192.168.0.1/24) 一.查看本机是否有安装telnetrpm -qa | grep telnetrpm -q telne ...

  10. 解决:win8.1 oepnvpn客户端 redirect-gateway def1无效,自动获取的IP没有网关问题

    解决:win8.1 oepnvpn客户端 redirect-gateway def1无效,自动获取的IP没有网关问题 该问题是操作系统权限问题,需要将程序设置为以管理员模式运行和以windows7兼容 ...