BZOJ 2806 [Ctsc2012]Cheat ——后缀自动机 单调队列优化DP
先建出广义后缀自动机。
然后跑出文章中每一个位置的最大匹配距离。
然后定义$f[i]$表示匹配到以$i$结尾的串时,最长的匹配距离。
显然可以二分$L$的取值。
然后容易得到$DP$方程
$f[i]=max(f[i-1],f[j]+i-j)(j<=i-L)$
然后就发现$j$属于一个区间,然后就可以单调队列优化了。
#include <map>
#include <ctime>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define maxn 2200005 namespace SAM{
int last,cnt,go[maxn][2],l[maxn],fa[maxn],n,m,q;
int f[maxn],que[maxn],hd,tl,d[maxn];
char s[maxn];
void init(){last=cnt=1;}
void add(int x)
{
int q,p=last;
if (q=go[p][x])
{
if (l[q]==l[p]+1) last=q;
else
{
int nq=last=++cnt;
l[nq]=l[p]+1;
memcpy(go[nq],go[q],sizeof go[q]);
fa[nq]=fa[q];fa[q]=nq;
for (;go[p][x]==q&&p;p=fa[p]) go[p][x]=nq;
last=nq;
}
}
else
{
int np=last=++cnt; l[np]=l[p]+1;
for (;p&&!go[p][x];p=fa[p]) go[p][x]=np;
if (!p) fa[np]=1;
else
{
q=go[p][x];
if (l[q]==l[p]+1) fa[np]=q;
else
{
int nq=++cnt;l[nq]=l[p]+1;
memcpy(go[nq],go[q],sizeof go[q]);
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
for (;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq;
}
}
}
}
void ins()
{
last=1;
scanf("%s",s+1); n=strlen(s+1);
F(i,1,n) add(s[i]-'0');
}
bool check(int mid)
{
f[0]=0; tl=0;hd=1;
F(i,1,n)
{
f[i]=f[i-1];int p=i-mid;
if (p>=0)
{
while (hd<=tl&&f[que[tl]]-que[tl]<f[i-mid]-p)tl--;
que[++tl]=p;
}
while (hd<=tl&&que[hd]<i-d[i]) hd++;
if (hd<=tl) f[i]=max(f[i],f[que[hd]]+i-que[hd]);
}
if (f[n]*10>=n*9) return true;
else return false;
}
void dp()
{
scanf("%s",s+1); n=strlen(s+1);
memset(d,0,(n+1)*sizeof(int));
int now=1,t=0;
F(i,1,n)
{
if (go[now][s[i]-'0'])
now=go[now][s[i]-'0'],t++;
else
{
while (now&&!go[now][s[i]-'0']) now=fa[now];
if (!now) now=1,t=0;
else t=l[now]+1,now=go[now][s[i]-'0'];
}
d[i]=t;
}
int l=0,r=n;
while (l<r)
{
int mid=(l+r)/2+1;
if (check(mid)) l=mid;
else r=mid-1;
}
printf("%d\n",l);
}
void solve()
{
init();
scanf("%d%d",&q,&m);
F(i,1,m) ins();
F(i,1,q) dp();
}
} int main()
{
using namespace SAM;
solve();
}
BZOJ 2806 [Ctsc2012]Cheat ——后缀自动机 单调队列优化DP的更多相关文章
- BZOJ 2806: [Ctsc2012]Cheat [广义后缀自动机 单调队列优化DP 二分]
2806: [Ctsc2012]Cheat 题意: 多个主串和多个询问串,每次询问将询问串分成多个连续子串,如果一个子串长度>=L且在主串中出现过就是熟悉的 如果熟悉的字符串长度>=询问串 ...
- bzoj 2806 [Ctsc2012]Cheat——广义后缀自动机+单调队列优化DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2806 只想着怎么用后缀数据结构做,其实应该考虑结合其他算法. 可以二分那个长度 L .设当前 ...
- BZOJ 2806 [Ctsc2012]Cheat (后缀自动机+二分+单调队列+dp)
题目大意: 给你一堆模式串和文本串 对于每个文本串,我们可以把它不可重叠地拆分成很多子串,如果拆分出的串作为子串出现在了任何一个模式串中,我们称它是“眼熟的”,我们必须保证“眼熟的”子串总长度不小于文 ...
- bzoj 2806: [Ctsc2012]Cheat 后缀自动机DP
2806: [Ctsc2012]Cheat Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 583 Solved: 330[Submit][Statu ...
- 【BZOJ2806】【CTSC2012】Cheat - 广义后缀自动机+单调队列优化DP
题意: Description Input 第一行两个整数N,M表示待检查的作文数量,和小强的标准作文库的行数 接下来M行的01串,表示标准作文库 接下来N行的01串,表示N篇作文 Output N行 ...
- 【BZOJ2806】Cheat 【广义后缀自动机+单调队列优化dp+二分】
题意 有M篇标准作文组成了一个作文库(每篇作文都是一个01的字符串),然后给出N篇作文(自然也是01字符串).如果一个长度不小于L的串在作文库中出现过,那么它是熟悉的.对于某一篇作文,我们要把它分为若 ...
- BZOJ 1010: [HNOI2008]玩具装箱toy | 单调队列优化DP
原题: http://www.lydsy.com/JudgeOnline/problem.php?id=1010 题解: #include<cstdio> #include<algo ...
- BZOJ 1499 [NOI2005] 瑰丽华尔兹 | 单调队列优化DP
BZOJ 1499 瑰丽华尔兹 | 单调队列优化DP 题意 有一块\(n \times m\)的矩形地面,上面有一些障碍(用'#'表示),其余的是空地(用'.'表示).每时每刻,地面都会向某个方向倾斜 ...
- bzoj 1499 [NOI2005]瑰丽华尔兹——单调队列优化dp
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1499 简单的单调队列优化dp.(然而当时却WA得不行.今天总算填了坑) 注意滚动数组赋初值应 ...
随机推荐
- Processing分形之一——Wallpaper
之前用C语言实现过一些分形,但是代码比较复杂.而对于天生对绘图友好的Processing,及其方便. 在大自然中分形普遍存在,我们用图形模拟,主要是找到一个贴近的函数. 代码 /** * Wallpa ...
- ListView适配器Adapter介绍与优化
一.ListView与Adapter的关系 ListView是Android开发过程中较为常见的组件之一,它将数据以列表的形式展现出来.一般而言,一个ListView由以下三个元素组成: 1.View ...
- python_91_正则表达式
常用的正则表达式: '.' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行 '^' 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r& ...
- vector 下标操作
比如:vector<int> ivec(3).. 当采用下标操作ivec[10]的时候,该操作是未定义的,在自己的机器上输出的值是零.建议使用迭代器进行操作.
- Linux 、AIX环境下查看oracle配置信息(service_name、SID、tnsname)。
SID: echo $ORACLE_SID service_name: sqlplus / as sysdba; show parameter instance_name; show paramete ...
- java 第11次作业:你能看懂就说明你理解了——this关键字
this 代表当前对象
- linux下libnet编程 亲自测试可用
linux下libnet编程 亲自测试可用 亲自测试 如果build包的时候 只要把类型改了 就能改成相应的协议. 0x0800 ip 0x0806 arp 0x86DD IPv6 0x86e ...
- I/O理解
I/O是什么 我的理解I/O就是用于读写的一个流 官方解释:I/O(英语:Input/Output),即输入/输出,通常指数据在内部存储器和外部存储器或其他周边设备之间的输入和输出. node中的io ...
- 01windows常用命令及批处理
1. 概述 复制内容:右键弹出快捷菜单,选择"标记(K)",然后选中所需要的内容,然后右键即可 粘贴内容:右键弹出快捷菜单,选择"粘贴(P)" 命令参数的路径: ...
- python入门:if和else的基本用法
#!/usr/bin/env python # -*- coding:utf-8 -*- #2.X用raw_input,3.X用input #if和else的基本用法 name = input(&qu ...