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)的更多相关文章

  1. [bzoj2806][Ctsc2012]Cheat(后缀自动机(SAM)+二分答案+单调队列优化dp)

    偷懒直接把bzoj的网页内容ctrlcv过来了 2806: [Ctsc2012]Cheat Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1943   ...

  2. BZOJ2806:[CTSC2012]Cheat(广义SAM,二分,DP)

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

  3. BZOJ2806 [Ctsc2012]Cheat 【后缀自动机 + 二分 + 单调队列优化DP】

    题目 输入格式 第一行两个整数N,M表示待检查的作文数量,和小强的标准作文库 的行数 接下来M行的01串,表示标准作文库 接下来N行的01串,表示N篇作文 输出格式 N行,每行一个整数,表示这篇作文的 ...

  4. BZOJ2806: [Ctsc2012]Cheat(广义后缀自动机,单调队列优化Dp)

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

  5. bzoj2806 [Ctsc2012]Cheat

    我们的目的就是找到一个最大的L0,使得该串的90%可以被分成若干长度>L0的字典串中的子串. 明显可以二分答案,对于二分的每个mid 我们考虑dp:f[i]表示前i个字符,最多能匹配上多少个字符 ...

  6. 【BZOJ2806】[Ctsc2012]Cheat 广义后缀自动机+二分+单调队列优化DP

    [BZOJ2806][Ctsc2012]Cheat Description Input 第一行两个整数N,M表示待检查的作文数量,和小强的标准作文库的行数接下来M行的01串,表示标准作文库接下来N行的 ...

  7. 【BZOJ 2806】 2806: [Ctsc2012]Cheat (SAM+二分+DP+单调队列)

    2806: [Ctsc2012]Cheat Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1262  Solved: 643 Description ...

  8. bzoj 2806: [Ctsc2012]Cheat 后缀自动机DP

    2806: [Ctsc2012]Cheat Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 583  Solved: 330[Submit][Statu ...

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

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

随机推荐

  1. os.clock()导致的bug

    os.clock () 功能:返回一个程序使用CPU时间的一个近似值 最近做了一个功能,这个功能需要统计时间间隔,例如每隔0.5秒做一次调用. 我用了os.clock()去统计时间,结果在pc机上都没 ...

  2. lua队列实现

    Queue = {} function Queue.newquene() } end function Queue.push(queue, value) queue.count = queue.cou ...

  3. tween.js 中文使用指南

    tween.js 英文使用指南 首先来看个例子: hello,tween.js 补间(动画)(来自 in-between)是一个概念,允许你以平滑的方式更改对象的属性.你只需告诉它哪些属性要更改,当补 ...

  4. python3爬虫:下载网易云音乐排行榜

    #!/usr/bin/python3# -*- encoding:utf-8 -*- # 网易云音乐批量下载 import requestsimport urllib # 榜单歌曲批量下载# r = ...

  5. Windows平台上使用ANT编译Hadoop Eclipse Plugin

    一.准备工作:   1.安装JDK 下载页面:http://www.oracle.com/technetwork/java/javase/downloads/index.html JDK6,JDK7都 ...

  6. C# 重命名文件方法

    . //重命名文件 // 改名方法 FileInfo fi = new FileInfo("旧路径"); //xx/xx/aa.rar fi.MoveTo("新路径&qu ...

  7. 企业级任务调度框架Quartz(8) 线程在Quartz里的意义(2)

    前序:      做为企业里的任务调度框架,出现同一时间点同时运行两个任务,或者两个任务因为开始的执行时间和执行时间的长短,很有可能出现任务并发执行的情况:因为Quartz的实现是采用java编程,那 ...

  8. PAT-树的同构

    链接 树的同构 题意 同构的定义: 给定两棵树T1和T2.如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的. 给两棵树,判断是否同构 做法 先建树,然后判断,知道怎么判断就知道 ...

  9. CentOS6.5 静默安装Oracle 11g过程中提示:Exception in thread “main” java.lang.NoClassDefFoundError

    原来是系统中设置了DISPLAY环境变量,执行: [oracle@qa26 database]$ ./runInstaller  -silent -responseFile /usr/local/or ...

  10. javaee 文件的写入

    package Shurushucu; import java.io.FileNotFoundException; import java.io.FileOutputStream; import ja ...