[CTSC2012]熟悉的文章 (后缀自动机 单调队列)
/*
首先答案显然是具有单调性的, 所以可以二分进行判断
然后当我们二分过后考虑dp来求最长匹配个数, 发现每个点能够转移的地点 肯定是一段区间, 然后这样就能够得到一个log^2算法
至于每个点的匹配最长区间, 我们可以预处理出所有地点的最长匹配串
然后发现这个东西可以进行单调栈优化, 原因是往后能往前最大匹配到的点是不会超过前面的, 否则前面那个也会更长
然后就能快乐地一个log了
*/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<iostream>
#define ll long long
#define M 2800010
#define mmp make_pair
using namespace std;
int read() {
int nm = 0, f = 1;
char c = getchar();
for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;
for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';
return nm * f;
}
char s[M];
int ch[M][2], cnt = 1, lst = 1, fa[M], len[M], n, m;
void insert(int c) {
int p = ++cnt, f = lst;
lst = p;
len[p] = len[f] + 1;
while(f && !ch[f][c]) ch[f][c] = p, f = fa[f];
if(f == 0) {
fa[p] = 1;
} else {
int q = ch[f][c];
if(len[q] == len[f] + 1) {
fa[p] = q;
} else {
int nq = ++cnt;
memcpy(ch[nq], ch[q], sizeof(ch[q]));
fa[nq] = fa[q];
len[nq] = len[f] + 1;
fa[p] = fa[q] = nq;
while(f && ch[f][c] == q) ch[f][c] = nq, f = fa[f];
}
}
}
int q[M], h, t, pre[M], f[M];
bool check(int k) {
int l = strlen(s + 1);
h = 1, t = 0;
for(int i = 1; i <= l; i++) {
f[i] = f[i - 1];
if(i < k) continue;
while(h <= t && f[q[t]] - q[t] <= f[i - k] - i + k) t--;
q[++t] = i - k;
while(h <= t && q[h] < i - pre[i]) h++;
if(h <= t) f[i] = max(f[i], f[q[h]] + i - q[h]);
}
return f[l] * 10 >= l * 9;
}
void getpre() {
int up = strlen(s + 1), now = 1, lenn = 0;
for(int i = 1; i <= up; i++) {
int c = s[i] - '0';
while(now && !ch[now][c]) now = fa[now], lenn = len[now];
if(!now) now = 1, lenn = 0;
else now = ch[now][c], lenn++;
pre[i] = lenn;
}
}
int work() {
getpre();
int l = 1, r = strlen(s + 1);
while(l + 1 < r) {
int mid = (l + r) >> 1;
if(check(mid)) l = mid;
else r = mid;
}
if(!check(l)) return -1;
if(check(r)) return r;
return l;
}
int main() {
n = read(), m = read();
for(int i = 1; i <= m; i++) {
lst = 1;
scanf("%s", s + 1);
int l = strlen(s + 1);
for(int j = 1; j <= l; j++) insert(s[j] - '0');
}
while(n--) {
scanf("%s", s + 1);
cout << work() << "\n";
}
return 0;
}
[CTSC2012]熟悉的文章 (后缀自动机 单调队列)的更多相关文章
- [CTSC2012]熟悉的文章(后缀自动机+动态规划)
题目描述 阿米巴是小强的好朋友. 在小强眼中,阿米巴是一个作文成绩很高的文艺青年.为了获取考试作文的真谛,小强向阿米巴求教.阿米巴给小强展示了几篇作文,小强觉得这些文章怎么看怎么觉得熟悉,仿佛是某些范 ...
- [CTSC2012]熟悉的文章 后缀自动机
题面:洛谷 题解: 观察到L是可二分的,因此我们二分L,然后就只需要想办法判断这个L是否可行即可. 因为要尽量使L可行,因此我们需要求出对于给定L,这个串最多能匹配上多少字符. 如果我们可以对每个位置 ...
- 【BZOJ2806】【CTSC2012】Cheat - 广义后缀自动机+单调队列优化DP
题意: Description Input 第一行两个整数N,M表示待检查的作文数量,和小强的标准作文库的行数 接下来M行的01串,表示标准作文库 接下来N行的01串,表示N篇作文 Output N行 ...
- 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
先建出广义后缀自动机. 然后跑出文章中每一个位置的最大匹配距离. 然后定义$f[i]$表示匹配到以$i$结尾的串时,最长的匹配距离. 显然可以二分$L$的取值. 然后容易得到$DP$方程 $f[i]= ...
- 【BZOJ2806】Cheat 【广义后缀自动机+单调队列优化dp+二分】
题意 有M篇标准作文组成了一个作文库(每篇作文都是一个01的字符串),然后给出N篇作文(自然也是01字符串).如果一个长度不小于L的串在作文库中出现过,那么它是熟悉的.对于某一篇作文,我们要把它分为若 ...
- P4022 [CTSC2012]熟悉的文章
题目 P4022 [CTSC2012]熟悉的文章 题目大意:多个文本串,多个匹配串,我们求\(L\),\(L\)指(匹配串中\(≥L\)长度的子串出现在文本串才为"熟悉",使得匹配 ...
- [CTSC2012]熟悉的文章(广义后缀自动机+二分答案+单调队列优化DP)
我们对作文库建出广义后缀自动机.考虑用\(SAM\)处理出来一个数组\(mx[i]\),表示从作文的第\(i\)个位置向左最远在作文库中出现的子串的长度.这个东西可以在\(SAM\)上跑\(trans ...
随机推荐
- Linux系统如何模拟Http的get或post请求?
一.get请求: 1.使用curl命令: curl “http://www.baidu.com” 如果这里的URL指向的是一个文件或者一幅图都可以直接下载到本地 curl -i “http://www ...
- 在CentOS6.8系统上安装MySQL5.7(转)
mysql-57">如何在CentOS 6.8系统上安装MySQL 5.7? 一.检查系统上是否已经安装MySQL 命令: ? 1 2 3 4 5 [root@localhost ~] ...
- DevExpress GridView 那些事儿
1:去除 GridView 头上的 "Drag a column header here to group by that column" --> 点击 Run Desig ...
- 比较字典推导式/dict()/通过键来构造的字典的速率 笔记
# 下面结果执行一次不容易出差距,所以都执行100000次 import time dict1 = {'a':1, 'b':2, 'c':3, 'd':4} # 第一种:字典推导式 start_tim ...
- windbg条件断点总结
1 . 条件断点是断点命令 ( bp 或者 bu ) 与j命令或者.if命令一起使用的,后面跟着一个gc命令 0:000> bp Address "j (Condition) 'O ...
- SSH实现隧道功能穿墙
Putty和SSH tunnel 目前寻求FQ的方式无非就几种: 寻找web代理(这个可以进我放置的在线代理进行测试) 自行寻找http/sock5代理(这个可以去网上搜索代理ip) vpnFQ(目前 ...
- oracle数据库使用小结
select * from r_patient a where a.birthdate= to_date('1953-03-01','yyyy-mm-dd');select * from r_pati ...
- Mysql 性能优化5【重要】数据库结构优化
数据库设计的步骤 我们大多使用mysql 设计三范式 设置时区
- STL基础--算法(修改数据的算法)
修改元素的算法 copy, move, transform, swap, fill, replace, remove vector<int> vec = {9,60,70,8,45,87, ...
- reids(缓存,reids下载,安装 测试)
什么是缓存:缓存就是数据交换的缓冲区(称作Cache),当某一硬件要读取数据时,会首先从缓存中查找需要的数据,如果找到了则直接执行,找不到的话则从内存中找.由于缓存的运行速度比内存快得多,故缓存的作用 ...