bzoj2806: [Ctsc2012]Cheat(SAM+DP)
2806: [Ctsc2012]Cheat
题目:传送门
题解:
感觉这题考的更多的就是DP啊...
看完题目的第一反应就是广义SAM...(然而并不会)
再YY一会儿想起来可以直接将作文库连成一个母串(中间用2隔开)去跑SAM,然后直接把文章当成是子串在自动机上面跑(字符串匹配问题的套路啊)
考虑DP:设f[i]表示前i个位置的最大匹配长度。那么f[i]=max(f[i],f[j]+i-j);
直接DP肯定爆炸,再考虑利用SAM来预处理一个match[],match[i]表示当前文章以第i个位置结尾的子串和作文库匹配的最长长度(直接在自动机里面乱跑)
L满足而分性,直接二分,然后我们会发现对于f[i]有影响的其实只在于[i-match[i],i-L],i-L这个玩意肯定单调递增啊...
一波单调队列直接搞:对于队头,如果位置在合法区间内,则直接可以找到最优解来更新f[i]
槽点:一开始被卡精度...%AC_Artist.zig_zag之后又WA了...然后发现自己脑残在check里memset。。。(做了一上午...菜啊),数据真的有点水
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
struct SAM
{
int son[],fail,dep;
SAM(){memset(son,,sizeof(son));fail=dep=;}
}ch[];int a[],match[],root,cnt,last;
int n,m;
char s[],st[];
void add(int k)
{
int x=a[k];
int p=last,np=++cnt;ch[np].dep=ch[p].dep+;
while(p && ch[p].son[x]==)ch[p].son[x]=np,p=ch[p].fail;
if(p==)ch[np].fail=root;
else
{
int q=ch[p].son[x];
if(ch[q].dep==ch[p].dep+)ch[np].fail=q;
else
{
int nq=++cnt;ch[nq]=ch[q];
ch[nq].dep=ch[p].dep+;
ch[np].fail=ch[q].fail=nq;
while(p && ch[p].son[x]==q)ch[p].son[x]=nq,p=ch[p].fail;
}
}
last=np;
}
void get_match(int len)
{
int p=root,sum=;
for(int i=;i<=len;i++)
{
int x=s[i]-'';
if(ch[p].son[x]!=)sum++,p=ch[p].son[x];
else //失配了就跳fail
{
while(p && ch[p].son[x]==)p=ch[p].fail;
if(p==)p=root,sum=;
else sum=ch[p].dep+,p=ch[p].son[x];
}
match[i]=sum;
}
}
int f[],list[];
bool check(int L,int len)
{
//if(L==0)return true;
f[]=;list[]=;
int p,head=,tail=;
for(int i=;i<=len;i++)
{
f[i]=f[i-];p=i-L;if(p<)continue;
while(head<=tail && f[p]+i-p>f[list[tail]]+i-list[tail])tail--;list[++tail]=p;
while(head<=tail && list[head]<i-match[i])head++;
if(head<=tail)f[i]=max(f[i],f[list[head]]+i-list[head]);
}
double anss=double(f[len])/double(len);
return anss>=0.8999999999;
}
int main()
{
scanf("%d%d",&n,&m);int la=;
cnt=;root=last=++cnt;
for(int i=;i<=m;i++)
{
scanf("%s",st+);int len=strlen(st+);int k=;
for(int j=la;j<=len+la-;j++)
{
k++;a[j]=st[k]-'';
add(j);
}
if(i!=m){la=len+la;a[la]=;add(la);la++;}
}
while(n--)
{
scanf("%s",s+);int len=strlen(s+);
get_match(len);
int l=,r=len,ans=;
while(l<=r)
{
int mid=(l+r)/;
if(check(mid,len))ans=mid,l=mid+;
else r=mid-;
}
printf("%d\n",ans);
}
return ;
}
bzoj2806: [Ctsc2012]Cheat(SAM+DP)的更多相关文章
- [bzoj2806][Ctsc2012]Cheat(后缀自动机(SAM)+二分答案+单调队列优化dp)
偷懒直接把bzoj的网页内容ctrlcv过来了 2806: [Ctsc2012]Cheat Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1943 ...
- BZOJ2806:[CTSC2012]Cheat(广义SAM,二分,DP)
Description Input 第一行两个整数N,M表示待检查的作文数量,和小强的标准作文库的行数 接下来M行的01串,表示标准作文库 接下来N行的01串,表示N篇作文 Output N行,每行一 ...
- BZOJ2806 [Ctsc2012]Cheat 【后缀自动机 + 二分 + 单调队列优化DP】
题目 输入格式 第一行两个整数N,M表示待检查的作文数量,和小强的标准作文库 的行数 接下来M行的01串,表示标准作文库 接下来N行的01串,表示N篇作文 输出格式 N行,每行一个整数,表示这篇作文的 ...
- BZOJ2806: [Ctsc2012]Cheat(广义后缀自动机,单调队列优化Dp)
Description Input 第一行两个整数N,M表示待检查的作文数量,和小强的标准作文库的行数接下来M行的01串,表示标准作文库接下来N行的01串,表示N篇作文 Output N行,每行一个整 ...
- bzoj2806 [Ctsc2012]Cheat
我们的目的就是找到一个最大的L0,使得该串的90%可以被分成若干长度>L0的字典串中的子串. 明显可以二分答案,对于二分的每个mid 我们考虑dp:f[i]表示前i个字符,最多能匹配上多少个字符 ...
- 【BZOJ2806】[Ctsc2012]Cheat 广义后缀自动机+二分+单调队列优化DP
[BZOJ2806][Ctsc2012]Cheat Description Input 第一行两个整数N,M表示待检查的作文数量,和小强的标准作文库的行数接下来M行的01串,表示标准作文库接下来N行的 ...
- 【BZOJ 2806】 2806: [Ctsc2012]Cheat (SAM+二分+DP+单调队列)
2806: [Ctsc2012]Cheat Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1262 Solved: 643 Description ...
- 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且在主串中出现过就是熟悉的 如果熟悉的字符串长度>=询问串 ...
随机推荐
- JDBC数据库中表更新
import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sq ...
- php对文件/目录操作的基础知识(图解)
具体的如下图所示:
- Redis之Ubuntu下Redis集群搭建
安装redis 首先下载redis $ wget http://download.redis.io/releases/redis-4.0.10.tar.gz $ .tar.gz $ cd redis- ...
- SEO规范(部分)
1:尽量减少AJAX的使用搜索引擎无法检索ajax中的内容,也无法识别javascript代码. 2:拒绝iframe,frame标签iframe,frame会极大的阻碍搜索引擎爬取网站内容. 3:图 ...
- 利用JavaScript的%做隔行换色
<html> <head> <meta charset="utf-8"> <title>无标题文档</title> &l ...
- div 内容水平垂直居中
对于前端布局来说.总有一些图片水平垂直居中老是不好看,影响整体美观,百度一大堆各种自适应方法,终于找到了一种比较简单,适用于所有场景的方法.. 1.对于布局来说.一个div搞定. <div id ...
- PHP入门及服务环境配置(Nginx+PHP)
PHP入门及服务环境配置(Nginx+PHP) PHP入门 PHP维基百科: PHP(全称:PHP:Hypertext Preprocessor,即"PHP:超文本预处理器")是一 ...
- java加密解密算法位运算
一.实例说明 本实例通过位运算的异或运算符 “ ^ ” 把字符串与一个指定的值进行异或运算,从而改变每个字符串中字符的值,这样就可以得到一个加密后的字符串.当把加密后的字符串作为程序输入内容,异或运算 ...
- 励志:98岁老爷爷用Windows系统自带画图软件制作的神作
哈尔拉斯科,是一位很出名的老爷爷,他70岁才接触MS Paint(就是我们熟知的Windows自带的画图软件).他曾经是一名图形艺术家,但是之前他都是手工创作.他熟知怎么用双手进行艺术创作.但是后来, ...
- Oracle中的SAVEPOINT
学习存储过程中使用断点回滚事务时,发现目前网络上存在一个问题,那就是使用断点回滚后,都忘记了一个很重要的事情,提交事务.虽然使用了断点回滚,但是断点回滚不像rollBack或commit一样结束当前事 ...