BZOJ 2806 Luogu P4022 [CTSC2012]Cheat (广义后缀自动机、DP、二分、单调队列)
题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=2806
(luogu) https://www.luogu.org/problemnew/show/P4022
题解:对“作文库”中的串建广义SAM。(感觉加个#拼在一起直接SAM也行啊,只是常数大了点,但是大家都写的广义SAM我也就跟着写广义SAM了233333)
询问时二分\(L\), 变成求最少几个位置不匹配。然后DP方程是\(dp[i]=\min(dp[i-1]+1,\min_{i-match[i]\le j\le i-L} dp[j])\). 其中\(match[j]\)表示以\(j\)结尾最长能匹配的子串长度,用后缀自动机求出。单调队列优化即可。
应该a[i]-=96我写成a[i]-=48; dp完了之后不更新ans; 二分分反……我是有多无脑
注意一个问题是,由于这里有\(mid\)的限制,只有\(\le i-mid\)的位置才能被放进单调队列, 不可以一上来就把\(0\)放进去!
代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1.1e6;
const int S = 2;
int son[(N<<1)+3][S+1];
int fa[(N<<1)+3];
int len[(N<<1)+3];
char a[N+3];
char b[N+3];
int match[N+3];
int dp[N+3];
int dq[N+3];
int n,m,siz,rtn,lstpos;
void initSAM()
{
siz = rtn = lstpos = 1;
}
void insertchar(char ch)
{
int p = lstpos,np; siz++; np = lstpos = siz; len[np] = len[p]+1;
for(; p && son[p][ch]==0; p=fa[p]) {son[p][ch] = np;}
if(!p) {fa[np] = rtn;}
else
{
int q = son[p][ch];
if(len[q]==len[p]+1) {fa[np] = q;}
else
{
siz++; int nq = siz; len[nq] = len[p]+1;
memcpy(son[nq],son[q],sizeof(son[q]));
fa[nq] = fa[q]; fa[np] = fa[q] = nq;
for(; p && son[p][ch]==q; p=fa[p]) {son[p][ch] = nq;}
}
}
}
int main()
{
initSAM();
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)
{
lstpos = rtn;
scanf("%s",a+1); int lena = strlen(a+1);
for(int j=1; j<=lena; j++) {insertchar(a[j]-48);}
}
for(int i=1; i<=n; i++)
{
scanf("%s",a+1); int lena = strlen(a+1);
for(int j=1; j<=lena; j++) {a[j]-=48;}
int u = rtn,cur = 0;
for(int j=1; j<=lena; j++)
{
while(u && son[u][a[j]]==0) {u = fa[u]; cur = len[u];}
if(son[u][a[j]]) {u = son[u][a[j]]; cur++;}
else {u = rtn; cur = 0;}
match[j] = cur;
}
int left = 0,right = lena,mid,ans;
while(left<right)
{
mid = (left+right+1)>>1;
dp[0] = 0; int head = 1,tail = 0;
if(mid<=1) {tail++; dq[tail] = 0;}
for(int j=1; j<=lena; j++)
{
dp[j] = dp[j-1]+1;
while(head<=tail && dq[head]<j-match[j]) {dq[head] = 0; head++;}
if(head<=tail)
{
dp[j] = min(dp[j],dp[dq[head]]);
}
if(j-mid+1>=0)
{
while(head<=tail && dp[dq[tail]]>=dp[j-mid+1]) {dq[tail] = 0; tail--;}
tail++; dq[tail] = j-mid+1;
}
}
ans = dp[lena];
if(ans*10<=lena) {left = mid;}
else {right = mid-1;}
}
printf("%d\n",left);
}
return 0;
}
BZOJ 2806 Luogu P4022 [CTSC2012]Cheat (广义后缀自动机、DP、二分、单调队列)的更多相关文章
- BZOJ.2806.[CTSC2012]Cheat(广义后缀自动机 DP 单调队列)
题目链接 首先二分答案L.然后就是判断能否将原串划分出一些长度不小于L的子串,这些子串要是给定n个串中的某个串的子串,且满足它们的长度之和不小于原串长度的90%. 贪心多长选一段什么的显然不对.老老实 ...
- BZOJ 2806: [Ctsc2012]Cheat [广义后缀自动机 单调队列优化DP 二分]
2806: [Ctsc2012]Cheat 题意: 多个主串和多个询问串,每次询问将询问串分成多个连续子串,如果一个子串长度>=L且在主串中出现过就是熟悉的 如果熟悉的字符串长度>=询问串 ...
- bzoj 2806 [Ctsc2012]Cheat——广义后缀自动机+单调队列优化DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2806 只想着怎么用后缀数据结构做,其实应该考虑结合其他算法. 可以二分那个长度 L .设当前 ...
- 【BZOJ2806】[Ctsc2012]Cheat 广义后缀自动机+二分+单调队列优化DP
[BZOJ2806][Ctsc2012]Cheat Description Input 第一行两个整数N,M表示待检查的作文数量,和小强的标准作文库的行数接下来M行的01串,表示标准作文库接下来N行的 ...
- 【BZOJ2806】Cheat(后缀自动机,二分答案,动态规划,单调队列)
[BZOJ2806]Cheat(后缀自动机,二分答案,动态规划,单调队列) 题面 BZOJ 洛谷 题解 很有趣的一道题啊 对于在所有的串上面进行匹配? 很明显的后缀自动机 所以先构建出广义后缀自动机 ...
- 【BZOJ2806】【CTSC2012】Cheat 广义后缀自动机+二分+Dp
题目 题目在这里 思路&做法 我们先对标准作文库建广义后缀自动机. 然后对于每一篇阿米巴的作文, 我们首先把放到广义后缀自动机跑一遍, 对于每一个位置, 记录公共子串的长度\((\)即代码和下 ...
- BZOJ.2780.[SPOJ8093]Sevenk Love Oimaster(广义后缀自动机)
题目链接 \(Description\) 给定n个模式串,多次询问一个串在多少个模式串中出现过.(字符集为26个小写字母) \(Solution\) 对每个询问串进行匹配最终会达到一个节点,我们需要得 ...
- BZOJ 4566 [Haoi2016]找相同字符 ——广义后缀自动机
建立广义后缀自动机. 然后统计子树中的siz,需要分开统计 然后对(l[i]-l[fa[i]])*siz[i][0]*siz[i][1]求和即可. #include <cstdio> #i ...
- 【BZOJ2806】【CTSC2012】Cheat - 广义后缀自动机+单调队列优化DP
题意: Description Input 第一行两个整数N,M表示待检查的作文数量,和小强的标准作文库的行数 接下来M行的01串,表示标准作文库 接下来N行的01串,表示N篇作文 Output N行 ...
随机推荐
- 如何在BCGControlBar工程的工具栏里面新增下拉列表控件
通常情况下,工具栏里面都是一些按钮和图片,很少可以看到下拉列表控件,但是在某些应用场合,也需要用到下拉列表控件.今天在这里就简单讲解下如何在工具栏里添加下拉列表控件. 添加的过程也比较简单,在CM ...
- Yii2笔记一
环境LNMP,通过Composer安装 安装Composer(已经安装请跳过) curl -s http://getcomposer.org/installer | php #php可执行文件所在位置 ...
- SSH协议、HTTPS中SSL协议的完整交互过程
1.(SSH)公私钥认证原理 服务器建立公钥:每一次启动sshd服务时,该服务会主动去找/etc/ssh/ssh_host*的文件 客户端通过ssh工具进行连接,如Xshell,SecureCRT 服 ...
- 为什么前后端分离不利于seo
搜索引擎的基础爬虫的原理就是抓取你的url,然后获取你的html源代码并解析. 而你的页面通常用了vue等js的数据绑定机制来展示页面数据,爬虫获取到的html是你的模型页面而不是最终数据的渲染页面, ...
- ASP.Net 知识点总结(四)
1.get和post 的区别 get是从服务器上获取数据,post是向服务器传送数据; get安全性非常低,数据显示在地址栏,post安全性较高: 但是执行效率却比Post方法好: get有字节限制为 ...
- 分享几篇有关react-native的博客
http://segmentfault.com/a/1190000002646155 http://facebook.github.io/react-native/docs/native-module ...
- .net环境下程序一些未知错误的调试
由于线程冲突等一系列原因导致的处理调试方法 1.打开[事件查看器]查找出错误的地方 [控制面板]-[系统和安全]-[管理工具]-[事件查看器]
- dubbo之日志适配及访问日志
日志适配 自 2.2.1 开始,dubbo 开始内置 log4j.slf4j.jcl.jdk 这些日志框架的适配 1,也可以通过以下方式显示配置日志输出策略: 命令行 java -Ddubbo.app ...
- Understanding and Analyzing Application Crash Reports
Introduction When an application crashes, a crash report is created and stored on the device. Crash ...
- Windows提高_2.1第一部分:线程
第一部分:线程 什么是线程? 线程其实可以理解为一段正在执行中的代码,它最少由一个线程内核对象和一个栈组成. 线程之间是没有从属关系的,同一进程下的所有线程都可以访问进程内的所有内容. 主线程其实是创 ...