Description

Input

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

Output

N行,每行一个整数,表示这篇作文的Lo 值。

Sample Input

1 2
10110
000001110
1011001100

Sample Output

4

解题思路:

L0值具有单调性。

L0值为0时,一定有匹配,为1时只需要考虑字符集,为2时要考虑前后顺序,所以具有单调性,L0越小匹配长度越大,那么可以二分。

这道题要求不能覆盖,所以不能使用简单的Dp来解决,但也很明显,得知一个字符串某一位为结尾时最长匹配长度是很有用的QAQ

所以设f[i]为以文本串i结尾,最长可识别子串的长度,那么startpos就是i-f[i],设Dp[i]表示匹配到i最长(可以不连续,但不小于L0)的最大匹配长度。

为了实现可不连续,Dp[i]初值为Dp[i-1],所以Dp[i]的转移方程就是Dp[i]=max(Dp[i-1],max({Dp[j]+i-j|i-j>=L0}))

转移是O(n2)的过不了,可以将Dp[j]-j与i分离将Dp[j]-j用单调队列维护,就是O(n)的了^_^

代码:

 #include<cstdio>
#include<cstring>
#include<algorithm>
struct sant{
int tranc[];
int len;
int pre;
}s[];
int siz;
int fin;
int n,m;
char tmp[];
int maxl[];
int dp[];
int x[];
void Insert(int c)
{
int nwp,nwq,lsp,lsq;
nwp=++siz;
s[nwp].len=s[fin].len+;
for(lsp=fin;lsp&&!s[lsp].tranc[c];lsp=s[lsp].pre)
s[lsp].tranc[c]=nwp;
if(!lsp)
s[nwp].pre=;
else{
lsq=s[lsp].tranc[c];
if(s[lsq].len==s[lsp].len+)
s[nwp].pre=lsq;
else{
nwq=++siz;
s[nwq]=s[lsq];
s[nwq].len=s[lsp].len+;
s[nwp].pre=s[lsq].pre=nwq;
while(s[lsp].tranc[c]==lsq)
{
s[lsp].tranc[c]=nwq;
lsp=s[lsp].pre;
}
}
}
fin=nwp;
return ;
}
bool can(int L0,int len)
{
dp[]=;
int t=,h=;
for(int i=;i<=len;i++)
{
dp[i]=dp[i-];
if(i<L0)
continue;
while(t>=h&&dp[x[t]]-x[t]<=dp[i-L0]-i+L0)t--;
x[++t]=i-L0;
while(t>=h&&x[h]<i-maxl[i])h++;
if(t>=h)
dp[i]=std::max(dp[x[h]]+i-x[h],dp[i]);
}
return *dp[len]>=*len;
}
int main()
{
fin=++siz;
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
scanf("%s",tmp+);
int len=strlen(tmp+);
fin=;
for(int j=;j<=len;j++)
Insert(tmp[j]-'');
}
while(n--)
{
scanf("%s",tmp+);
int len=strlen(tmp+);
int root=;
int mxl=;
for(int i=;i<=len;i++)
{
int c=tmp[i]-'';
if(s[root].tranc[c])
{
root=s[root].tranc[c];
mxl++;
}else{
while(!s[root].tranc[c])
root=s[root].pre;
if(!root)
{
root=;
mxl=;
}else{
mxl=s[root].len+;
root=s[root].tranc[c];
}
}
maxl[i]=mxl;
}
int ans=;
int l=,r=len;
while(l<=r)
{
int mid=(l+r)>>;
if(can(mid,len))
{
ans=mid;
l=mid+;
}else
r=mid-;
}
printf("%d\n",ans);
}
return ;
}

BZOJ2806: [Ctsc2012]Cheat(广义后缀自动机,单调队列优化Dp)的更多相关文章

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

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

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

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

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

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

  4. 【BZOJ2806】Cheat 【广义后缀自动机+单调队列优化dp+二分】

    题意 有M篇标准作文组成了一个作文库(每篇作文都是一个01的字符串),然后给出N篇作文(自然也是01字符串).如果一个长度不小于L的串在作文库中出现过,那么它是熟悉的.对于某一篇作文,我们要把它分为若 ...

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

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

  6. BZOJ 2806 Luogu P4022 [CTSC2012]Cheat (广义后缀自动机、DP、二分、单调队列)

    题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=2806 (luogu) https://www.luogu.org/pro ...

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

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

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

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

  9. BZOJ.2806.[CTSC2012]Cheat(广义后缀自动机 DP 单调队列)

    题目链接 首先二分答案L.然后就是判断能否将原串划分出一些长度不小于L的子串,这些子串要是给定n个串中的某个串的子串,且满足它们的长度之和不小于原串长度的90%. 贪心多长选一段什么的显然不对.老老实 ...

  10. 【BZOJ2806】Cheat(后缀自动机,二分答案,动态规划,单调队列)

    [BZOJ2806]Cheat(后缀自动机,二分答案,动态规划,单调队列) 题面 BZOJ 洛谷 题解 很有趣的一道题啊 对于在所有的串上面进行匹配? 很明显的后缀自动机 所以先构建出广义后缀自动机 ...

随机推荐

  1. TRIZ系列-创新原理-7-嵌套原理

    原理表述例如以下: 1)把一个物体嵌入另外一个物体.然后将这两个物体再嵌入第三个物体,以此类推. 这个原理又叫俄罗斯娃原理,目的是在不影响原有功能的情况下: A) 在须要时.能够降低系统的体积和便于携 ...

  2. .Net中字典的使用

    /// <summary> /// 获取用户市信息 /// </summary> /// <param name="CustomerId">&l ...

  3. legend---四、菜鸟教程css3里面有教你炫酷的按钮怎么做

    legend---四.菜鸟教程css3里面有教你炫酷的按钮怎么做 一.总结 一句话总结:想学,总是有很多资料的 1. 自动居中是 margin:100px 0px;么? 自动居中是margin:100 ...

  4. SQL函数_Charindex()

    1 charindex()函数的作用是用于发现目标字符串第一次出现在源字符串中出现的开始位置. 语法如下 : select charinde(目标字符串,列名或字符串[,起始位置]) from 表名

  5. 大吉大利,晚饭吃鸡!——accept关闭问题

    假期收尾了,学芽子们都军训了.一群张一山和周冬雨在校内晃晃悠悠,说起来春风十里也就军训比较有意思.对于我这种一年追一部剧的人,显然是有点对不住.在我假期任务即将圆满之际,我开始放慢脚步寻找生活的美妙时 ...

  6. python yield学习

    yield的功能类似于return,但是不同之处在于它返回的是生成器. 生成器生成器是通过一个或多个yield表达式构成的函数,每一个生成器都是一个迭代器(但是迭代器不一定是生成器). 如果一个函数包 ...

  7. React开发实时聊天招聘工具 -第六章 登陆注册(1)

    1.基于cookie的用户认证 express 依赖 cookie-parser 2.axios语法: axios.get('/data').then(res=>{ if(res.status= ...

  8. Centos7部署phpMyAdmin系统

    phpMyAdmin是一个使用PHP语言编写,用来管理MYSQL数据库的Web应用系统 一:安装phpMyadmin 下载phpMyadmin最新版本4.8 wget https://files.ph ...

  9. ListView常用操作

    1.设置ListView只显示一列,并且每加一条记录是向下添加的. ListView添加方法:把View属性改成Details,再Columns属性中添加一列 然后用如下代码即可实现 ListView ...

  10. [Python] Format Strings in Python

    Single quotes and double quotes can both be used to declare strings in Python. You can even use trip ...