BZOJ 2806 cheat
首先这个题目显然是要二分转换成判断可行性的
之后我们考虑DP
设f(i)表示 1->i 熟悉的子串的长度的最大值
那么对于i这个点,要么不在熟悉的子串中,要么在熟悉的子串中
所以得到
f(i)=max(f(i-1),f(j)+i-j);
其中i-j是划分的熟悉的子串的长度,要满足以下条件:
1、i-j>=k (k为二分出来的值)
2、[j+1,i]这段串是给定标准文章库的一个子串
我们又知道若[j+1,i]是一个满足条件的子串,那么[j+2,i]也一定满足条件
假设我们已知最小的p满足[p+1,i]是一个满足条件的子串,定义L=i-p
那么条件2转化为 i-j<=L
求特定区间的最大值,且左右端点是单调的,我们是可以用单调队列的
那么现在问题就是求解最小的p使得[p+1,i]满足条件
即求解给定串S的一个前缀的最长满足条件的后缀,这时可以用后缀自动机做的
每次只需要在上次的基础上顺着parent树向上寻找匹配就可以了
注意:当寻找到SAM上的一个可匹配的节点时,当前的L并不一定是这个合法节点的len值+1
因为SAM上的节点的len值为其可以取得的长度的最大值,它有可能比上一次的L要大
所以我的代码对这种情况进行了一下处理QAQ
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<algorithm>
using namespace std; const int maxn=1100010;
int n,m,cnt,la,len;
char s[maxn];
struct Node{
int next[3];//0 1 2
int len,link;
}st[maxn<<1];
int Q[maxn],h,t;
int f[maxn]; void init(){
cnt=la=0;
st[0].link=-1;
}
void add(int c){
int cur=++cnt;
st[cur].len=st[la].len+1;
int p;
for(p=la;p!=-1&&st[p].next[c]==0;p=st[p].link)st[p].next[c]=cur;
if(p==-1)st[cur].link=0;
else{
int q=st[p].next[c];
if(st[q].len==st[p].len+1)st[cur].link=q;
else{
int clone=++cnt;
st[clone]=st[q];
st[clone].len=st[p].len+1;
for(;p!=-1&&st[p].next[c]==q;p=st[p].link)st[p].next[c]=clone;
st[q].link=st[cur].link=clone;
}
}la=cur;
}
bool check(int k){
h=1;t=0;f[0]=0;
int p=0,L=0;
for(int i=1;i<=len;++i){
if(i>=k){
while(h<=t&&f[Q[t]]-Q[t]<f[i-k]-(i-k))t--;
Q[++t]=i-k;
}
int now=s[i]-'0';
int cur=p;
for(;p!=-1&&st[p].next[now]==0;p=st[p].link);
f[i]=f[i-1];
if(p==-1){p=0;L=0;continue;}
if(p==cur)L++;
else L=st[p].len+1;
p=st[p].next[now];
while(h<=t&&i-Q[h]>L)h++;
if(h<=t)f[i]=max(f[i],f[Q[h]]-Q[h]+i);
}return len*9<=f[len]*10;
} int main(){
scanf("%d%d",&n,&m);init();
for(int i=1;i<=m;++i){
scanf("%s",s+1);len=strlen(s+1);
for(int j=1;j<=len;++j)add(s[j]-'0');
add(2);
}
while(n--){
scanf("%s",s+1);len=strlen(s+1);
int L=0,R=len;
while(L<R){
int mid=L+((R-L+1)>>1);
if(check(mid))L=mid;
else R=mid-1;
}printf("%d\n",L);
}return 0;
}
BZOJ 2806 cheat的更多相关文章
- [CTSC 2012][BZOJ 2806]Cheat
真是一道好题喵~ 果然自动机什么的就是要和 dp 搞基才是王道有木有! A:连 CTSC 都叫我们搞基,果然身为一个程序猿,加入 FFF 团是我此生最明智的选择.妹子什么闪边去,大家一起来搞基吧! Q ...
- 后缀自动机SAM BZOJ 2806
终于遇到了一道后缀数组不能过 一定要学SAM的题... (看了半个下午+半个上午) 现在总结一下(是给我自己总结..所以只总结了我觉得重要的 .. 看不太懂的话可以To http://blog.c ...
- bzoj 2806: [Ctsc2012]Cheat 后缀自动机DP
2806: [Ctsc2012]Cheat Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 583 Solved: 330[Submit][Statu ...
- BZOJ 2806: [Ctsc2012]Cheat [广义后缀自动机 单调队列优化DP 二分]
2806: [Ctsc2012]Cheat 题意: 多个主串和多个询问串,每次询问将询问串分成多个连续子串,如果一个子串长度>=L且在主串中出现过就是熟悉的 如果熟悉的字符串长度>=询问串 ...
- 【BZOJ 2806】 2806: [Ctsc2012]Cheat (SAM+二分+DP+单调队列)
2806: [Ctsc2012]Cheat Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1262 Solved: 643 Description ...
- BZOJ 2806 Luogu P4022 [CTSC2012]Cheat (广义后缀自动机、DP、二分、单调队列)
题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=2806 (luogu) https://www.luogu.org/pro ...
- bzoj 2806: [Ctsc2012]Cheat
传送门 好久没刷bzoj惹…… 题意不说可以嘛. 首先二分答案. SAM的事情搞完以后就是dp辣. 我们已经对于每个位置i,找到了最小的一个k,使得[k,i]这个子串在模版串中出现过.那么我们需要做的 ...
- bzoj 2806 [Ctsc2012]Cheat——广义后缀自动机+单调队列优化DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2806 只想着怎么用后缀数据结构做,其实应该考虑结合其他算法. 可以二分那个长度 L .设当前 ...
- BZOJ 2806 【CTSC2012】 Cheat
题目链接:Cheat 话说这道题很久以前某人就给我们考过,直到现在,我终于把这个坑填上了…… 这道题要我们把一个串\(S\)划分成若干块,每块长度不小于\(L_0\),使得能够在文章库中完全匹配的块的 ...
随机推荐
- PHP标签的格式
PHP标签的格式: 1.xml格式(推荐的,标准的标记) <?php php代码?> 示例: 2.短格式 <? php代码 ?> 此种格式需要在php.ini中配置 示例 ...
- 笔试面试题-寻找Coder
请设计一个高效算法,再给定的字符串数组中,找到包含"Coder"的字符串(不区分大小写),并将其作为一个新的数组返回.结果字符串的顺序按照"Coder"出现的次 ...
- C++ 的隱式型別轉換
先上一段代碼, 這段代碼竟然可以編譯過,我的老天! class Boo { Boo(int c){ cout << "I'm Boo"; } }; void do_so ...
- 把div固定在网页顶部
很多网站都有把某一块固定在顶部的功能,今天上网搜搜然后自己又写了一遍,贴出来给大家看看,哪天用到的时候自己也可以随时看看 <!DOCTYPE html PUBLIC "-//W3C// ...
- DevExpress gridView 小结(一)
一:第一列显示行号 CustomDrawRowIndicator this.gridViewDevice.IndicatorWidth = 40; this.gridViewDevice.Custo ...
- JS滑动门,JQuery滑动门
<a href="#" id="one1" onmouseover="setTab('one',1,2)" class="h ...
- 菜鸟聊:PHP
学习PHP已经有2个月时间了,从一开始的一片空白,到现在的刚刚入门,我对PHP的了解也有更多的认知,希望通过我对PHP的理解,能帮助到更多像我一样的新手更早的认识PHP.(PS:以下内容的一部分是摘自 ...
- linux下rm误删除数据库文件的恢复方法
在linux redhat 5.4版本,rm误删除数据库文件的恢复过程分享.测试没有问题,可用. 1.首先测试rm 误删除数据库文件 [oracle@primary dbwdn]$ ll total ...
- jQuery回车事件
有网就是好. 全局事件: document.onkeydown=function(e){ var ev=document.all?window.evevt:e; if(ev.keyCode==13){ ...
- ajax的post用法
<button>点击之后,显示ajax返回的数据</button> 首先在页面上新建了一个按钮,点击这个按钮后,执行ajax操作,并将返回的字符串显示在按钮上. 下面是ajax ...