BZOJ 2806: [Ctsc2012]Cheat(单调队列优化dp+后缀自动机)
解题思路
肯定先要建出来广义后缀自动机。刚开始以为是个二分+贪心,写了一下结果\(20\)分。说一下正解,首先显然\(L_0\)具有单调性,是可以二分的。考虑二分后怎样判合法,对于分割序列很容易想到\(dp\),设\(f_i\)表示前\(i\)个字符匹配成功数量,那么有转移方程\(f_i=max(f_j+i-j)(i-j>=L\) 且 \(j\)到\(i\)可以匹配 \()\),\(L\)是二分出来的限制,判断是否能匹配可以预处理,预处理出\(mth_i\)表示\(i\)最多能与往前\(mth_i\)位匹配成功,那么第二个条件就变成了\(j>=i-mth_i\)。如果这样做是\(O(n^2logn)\)的,实测可以拿到\(75\)分2333。考虑优化,发现\(i-mth_i\)具有单调性,因为每移动一格\(i\)会\(+1\),而\(mth_i\)最多\(+1\)。那么可以用一个单调递减队列来优化,每次将\(i-lim\)入队,取出队头更新答案,时间复杂度为\(O(nlogn)\)。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=1100005<<1;
int n,m,res,ans,f[N],mth[N],q[N],hd,tl;
char s[N];
struct SAM{
int ch[N][2],fa[N],l[N],lst,cnt;
void Insert(int c){
int p=lst,np=++cnt; l[np]=l[p]+1; lst=cnt;
for(;p && !ch[p][c];p=fa[p]) ch[p][c]=np;
if(!p) fa[np]=1;
else {
int q=ch[p][c];
if(l[p]+1==l[q]) fa[np]=q;
else {
int nq=++cnt; l[nq]=l[p]+1;
memcpy(ch[nq],ch[q],sizeof(ch[nq]));
fa[nq]=fa[q]; fa[q]=fa[np]=nq;
for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
}
}
}
void prework(int len){
int now=1,num=0;
for(int i=1;i<=len;i++){
if(ch[now][s[i]-'0']) now=ch[now][s[i]-'0'],num++;
else {
for(;now && !ch[now][s[i]-'0'];now=fa[now]);
if(!now) now=1,num=0;
else num=l[now]+1,now=ch[now][s[i]-'0'];
}
mth[i]=num;
}
}
bool check(int lim,int len){
int tmp; hd=1; tl=0;
for(int i=1;i<=len;i++){
f[i]=f[i-1]; if(i<lim) continue; tmp=i-mth[i];
while(hd<=tl && f[q[tl]]-q[tl]<=f[i-lim]-i+lim) tl--;
q[++tl]=i-lim;
while(hd<=tl && q[hd]<tmp) hd++;
if(hd<=tl) f[i]=max(f[i],f[q[hd]]-q[hd]+i);
}
// for(int i=1;i<=len;i++){
// f[i]=f[i-1];
// for(int j=max(0,i-mth[i]);j+lim<=i;j++)
// f[i]=max(f[i],f[j]+i-j);
// }
return len-f[len]>res?0:1;
}
void solve(int len){
prework(len);
int L=1,R=len,mid;
while(L<=R){
mid=(L+R)>>1;
if(check(mid,len)) L=mid+1,ans=mid;
else R=mid-1;
}
printf("%d\n",ans);
}
}sam;
int main(){
scanf("%d%d",&n,&m); sam.cnt=1; int len;
for(int i=1;i<=m;i++){
scanf("%s",s+1); sam.lst=1;
len=strlen(s+1);
for(int j=1;j<=len;j++) sam.Insert(s[j]-'0');
}
for(int i=1;i<=n;i++){
scanf("%s",s+1); len=strlen(s+1);
res=(len*9+9)/10; res=len-res;
sam.solve(len); ans=0;
}
return 0;
}
BZOJ 2806: [Ctsc2012]Cheat(单调队列优化dp+后缀自动机)的更多相关文章
- bzoj 2216: Lightning Conductor 单调队列优化dp
题目大意 已知一个长度为\(n\)的序列\(a_1,a_2,...,a_n\)对于每个\(1\leq i\leq n\),找到最小的非负整数\(p\)满足: 对于任意的\(j\), \(a_j \le ...
- BZOJ 1233 干草堆 (单调队列优化DP)
$ BZOJ~1233~~ $ 干草堆: (题目特殊性质) $ solution: $ 很妙的一道题目,开始看了一眼觉得是个傻逼贪心,从后往前当前层能多短就多短,尽量节省花费.但是这是DP专题,怎么会 ...
- BZOJ 1855 股票交易(单调队列优化DP)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1855 题意:最近lxhgww又迷上了投资股票, 通过一段时间的观察和学习,他总结出了股票 ...
- 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得不行.今天总算填了坑) 注意滚动数组赋初值应 ...
- 单调队列优化DP || [NOI2005]瑰丽华尔兹 || BZOJ 1499 || Luogu P2254
题外话:题目极好,做题体验极差 题面:[NOI2005]瑰丽华尔兹 题解: F[t][i][j]表示第t时刻钢琴位于(i,j)时的最大路程F[t][i][j]=max(F[t-1][i][j],F[t ...
- P4381 [IOI2008]Island(基环树+单调队列优化dp)
P4381 [IOI2008]Island 题意:求图中所有基环树的直径和 我们对每棵基环树分别计算答案. 首先我们先bfs找环(dfs易爆栈) 蓝后我们处理直径 直径不在环上,就在环上某点的子树上 ...
- 【笔记篇】单调队列优化dp学习笔记&&luogu2569_bzoj1855股票交♂易
DP颂 DP之神 圣洁美丽 算法光芒照大地 我们怀着 崇高敬意 跪倒在DP神殿里 你的复杂 能让蒟蒻 试图入门却放弃 在你光辉 照耀下面 AC真心不容易 dp大概是最经久不衰 亘古不化的算法了吧. 而 ...
- 单调队列优化DP,多重背包
单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...
随机推荐
- git查看某个文件的提交历史
1. git log --pretty=oneline 文件名 文件名是文件路径+文件名,输入完整 输入正确后,打印出版本号的列表 2. git show <git提交版本号> <文 ...
- 使用 GitLab 的 OAuth2 认证服务
原文地址 本文档讲述如何使用 GitLab 作为 OAuth 认证服务提供商,以通过 GitLab 的 OAuth 认证登录其他服务(例如持续集成工具 Drone). 如果想使用其他 OAuth 身份 ...
- 深入浅出WPF(Binding篇1)
Binding在业界的使用一直是音译而来的,称为"Binding".Binding的源是逻辑数据对象,目标则是UI层上面的控件对象.数据通过Binding送达UI层,被UI层展示出 ...
- (appium+python)UI自动化_10_adb常用命令
前言 adb(Android Debug Bridge)工具是android-sdk里的一个工具,是一个命令行窗口,用于通过电脑端与模拟器或者真实设备交互.在app自动化测试过程中,有时要用到adb命 ...
- 洛谷P5018 对称二叉树——hash
给一手链接 https://www.luogu.com.cn/problem/P5018 这道题其实就是用hash水过去的,我们维护两个hash 一个是先左子树后右子树的h1 一个是先右子树后左子树的 ...
- MapReduce-WordCountDemo
/** * @Author: dreamer Q * @Date: 2019/11/4 22:26 * @Version 1.0 * @Discription 使用MapReduce 开发 WordC ...
- JavaScript 内置对象 Array 数组
Array 数组 1.创建数组 构造函数 new Array() 小括号内可以是数组元素个数,也可以是数组项 数组字面量表示法 var arr = [1,2,3,4,5]; 2.数组长度 arr.le ...
- 268-基于FMC接口的DSP TMS320C6657子卡模块
基于FMC接口的DSP TMS320C6657子卡模块 一. 概述 FMC连接器是一种高速多pin的互连器件,广泛应用于板卡对接的设备中,特别是在xilinx公司的所有开发板中都使用. ...
- Codeforces Round #392 (Div. 2) - A
题目链接:http://codeforces.com/contest/758/problem/A 题意:给定N个城市的福利,国王现在想让每个城市的福利都一致.问最少需要花多少钱使得N个城市的福利值都一 ...
- json字符串处理—Json&C#
C# 转自:https://blog.csdn.net/sajiazaici/article/details/77647625# 本文是全网第二简单的方法,因为我女票也发了一篇博客说是全网最简单的方法 ...