【BZOJ2806】Cheat 【广义后缀自动机+单调队列优化dp+二分】
题意
有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+二分】的更多相关文章
- BZOJ 2806: [Ctsc2012]Cheat [广义后缀自动机 单调队列优化DP 二分]
2806: [Ctsc2012]Cheat 题意: 多个主串和多个询问串,每次询问将询问串分成多个连续子串,如果一个子串长度>=L且在主串中出现过就是熟悉的 如果熟悉的字符串长度>=询问串 ...
- 【BZOJ2806】【CTSC2012】Cheat - 广义后缀自动机+单调队列优化DP
题意: Description Input 第一行两个整数N,M表示待检查的作文数量,和小强的标准作文库的行数 接下来M行的01串,表示标准作文库 接下来N行的01串,表示N篇作文 Output N行 ...
- bzoj 2806 [Ctsc2012]Cheat——广义后缀自动机+单调队列优化DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2806 只想着怎么用后缀数据结构做,其实应该考虑结合其他算法. 可以二分那个长度 L .设当前 ...
- BZOJ 2806 [Ctsc2012]Cheat ——后缀自动机 单调队列优化DP
先建出广义后缀自动机. 然后跑出文章中每一个位置的最大匹配距离. 然后定义$f[i]$表示匹配到以$i$结尾的串时,最长的匹配距离. 显然可以二分$L$的取值. 然后容易得到$DP$方程 $f[i]= ...
- 单调队列优化DP,多重背包
单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...
- 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 ...
- hdu3401:单调队列优化dp
第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...
- Parade(单调队列优化dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others) ...
- BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP
BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...
随机推荐
- specialized English for automation-Lesson 3 CMOS Logic Circuit
CMOS logic is a newer technology, based on the use of complementary MOS transistors toperform logic ...
- 【linux】查看进程
查询所有:ps aux 查询某个用户:ps -u abc 终止某个进程:kill
- 手动整合实现SSH项目开发02
在bean包下建立User类和User.hbm.xml文件,实现User类和数据库表User的映射关系,具体User类不多说,User.hbm.xml如下: <?xml version=&quo ...
- java 8 新特性之Stream的排序/分类
Stream简介 Stream是Java8提供的一个新的API,它位于java.util.stream包下.Stream API提供了一种新的方式来对Java集合进行操作,这种操作方式极大的提高了Ja ...
- 2018-2019-2 《网络对抗技术》Exp4 恶意代码分析 20165222李勖
1.系统运行监控 (1)使用如计划任务,每隔一分钟记录自己的电脑有哪些程序在联网,连接的外部IP是哪里.运行一段时间并分析该文件,综述一下分析结果.目标就是找出所有连网的程序,连了哪里,大约干了什么( ...
- ORA-01033: ORACLE initialization or shutdown in progress --手动删除表空间 DBF 后无法登陆问题
进入CMD,执行set ORACLE_SID=fbms,确保连接到正确的SID: 2.执行sqlplus "/as sysdba" SQL>shutdown immediat ...
- VsCode中运行nodeJs代码的简单方法
VsCode安装包默认内置的node debug插件需要配置工程调试运行文件才能正常运行,对于想要运行一个简单的js文件或者就是一段js代码时比较麻烦,为此可以安装Code Runner插件 安装完后 ...
- curl查询公网出口IP
liuzhizhi@lzz-rmbp|logs # curl ipinfo.io { "ip": "114.110.1.38", "hostname& ...
- Spring Boot 入门之消息中间件篇(五)
原文地址:Spring Boot 入门之消息中间件篇(五) 博客地址:http://www.extlight.com 一.前言 在消息中间件中有 2 个重要的概念:消息代理和目的地.当消息发送者发送消 ...
- rsync 通过密码文件实现远程同步
https://my.oschina.net/yyping/blog/91964 1.源文件服务器:192.168.10.203 2.备份服务器:192.168.10.88 配置备份服务器(192.1 ...