@atcoder - AGC024F@ Simple Subsequence Problem
@description@
给定由若干长度 <= N 的 01 字符串组成的集合 S。请找到长度最长的串 t(如果有多个选字典序最小的),使得存在 >= K 个 S 中的字符串,使得 t 是这些字符串的子序列。
@solution@
先看看怎么检验串 t 是否为某个串 s 的子序列:从前往后匹配,贪心地找最前面一个能够匹配上的。
注意到匹配的过程可以建图:每个种类的串 s 建点,向第一次出现的 0/1 对应的后缀连边。
每个点的连边是 O(1),因此假如把所有 <= N 的串建这个图,实际得到的图也不会很大。
于是就有一个思路:枚举 t,每次将 S 中的串对应的点在这个图上进行移动,看剩余的点是否依然 >= K 个。
看似会 TLE,然而可以修正一下:如果两个字符串走到了同一个点,下一次只移动这一个点即可。
看似还会 TLE,实际上可以过了。
因为每个长度为 p 的字符串会有 2^p 种可能性,而它继续往下匹配只会剩下 2^(N-p) 种匹配可能。因此每一个 p 都是 O(2^N) 的复杂度。
因此总复杂度为 O(N*2^N) (应该是吧,没有认真算过)。
@accepted code@
#include <cstdio>
int ch[2][1<<22], id[22][1<<21], cnt;
void get() {
id[0][0] = (cnt++), ch[0][id[0][0]] = ch[1][id[0][0]] = -1;
for(int i=1;i<=20;i++) {
int t = (1 << i), k = (t >> 1);
for(int s=0;s<t;s++) {
id[i][s] = (cnt++);
int p = (s & k), q = (p ? 1 : 0);
ch[q][id[i][s]] = id[i-1][s^p];
ch[!q][id[i][s]] = ch[!q][id[i-1][s^p]];
}
}
}
int a[22][1<<22], siz[22], c[22][1<<22], num[22][1<<22];
int ans[22], N, K;
void dfs(int d, int s) {
if( ans[d] == -1 ) ans[d] = s;
for(int p=0;p<=1;p++) {
int tot = 0;
for(int i=0;i<siz[d];i++) {
int to = ch[p][a[d][i]];
if( to == -1 ) continue;
if( num[d + 1][to] == -1 )
num[d + 1][a[d + 1][siz[d + 1]] = to] = siz[d + 1], siz[d + 1]++;
tot += c[d][i], c[d + 1][num[d + 1][to]] += c[d][i];
}
if( tot >= K ) dfs(d + 1, (s << 1) | p);
for(int i=0;i<siz[d + 1];i++)
num[d + 1][a[d + 1][i]] = -1, c[d + 1][i] = 0;
siz[d + 1] = 0;
}
}
char s[1<<21];
int main() {
scanf("%d%d", &N, &K), get();
for(int i=0;i<=N;i++)
for(int j=0;j<cnt;j++)
num[i][j] = -1;
for(int i=0;i<=N;i++) {
scanf("%s", s);
int t = (1 << i);
for(int j=0;j<t;j++) {
if( s[j] == '1' )
num[0][a[0][siz[0]] = id[i][j]] = siz[0], c[0][num[0][id[i][j]]]++, siz[0]++;
}
ans[i] = -1;
}
dfs(0, 0);
for(int i=N;i>=0;i--) {
if( ans[i] != -1 ) {
for(int j=i-1;j>=0;j--)
putchar(((ans[i] >> j) & 1) + '0');
puts(""); return 0;
}
}
}
@details@
事实证明再怎么精打细算还是有想象之外的越界危险。
还不如直接数组开大 2 倍。
@atcoder - AGC024F@ Simple Subsequence Problem的更多相关文章
- [题解] [AGC024F] Simple Subsequence Problem
题目大意 有一个 01 串集合 \(S\),其中每个串的长度都不超过 \(N\),你要求出 \(S\) 中至少是 \(K\) 个串的子序列的最长串,如果有多解,输出字典序最小的那组解. 由于 \(S\ ...
- BZOJ 3489: A simple rmq problem
3489: A simple rmq problem Time Limit: 40 Sec Memory Limit: 600 MBSubmit: 1594 Solved: 520[Submit] ...
- ZOJ 3686 A Simple Tree Problem
A Simple Tree Problem Time Limit: 3 Seconds Memory Limit: 65536 KB Given a rooted tree, each no ...
- hdu4976 A simple greedy problem. (贪心+DP)
http://acm.hdu.edu.cn/showproblem.php?pid=4976 2014 Multi-University Training Contest 10 1006 A simp ...
- hdu 1757 A Simple Math Problem (乘法矩阵)
A Simple Math Problem Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- HDU1757 A Simple Math Problem 矩阵快速幂
A Simple Math Problem Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- hdu------(1757)A Simple Math Problem(简单矩阵快速幂)
A Simple Math Problem Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- bzoj 3489: A simple rmq problem k-d树思想大暴力
3489: A simple rmq problem Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 551 Solved: 170[Submit][ ...
- SPOJ LIS2 Another Longest Increasing Subsequence Problem 三维偏序最长链 CDQ分治
Another Longest Increasing Subsequence Problem Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://a ...
随机推荐
- 教你避过安装TensorFlow的两个坑
TensorFlow作为著名机器学习相关的框架,很多小伙伴们都可能要安装它.WIN+R,输入cmd运行后,通常可能就会pip install tensorflow直接安装了,但是由于这个库比较大,接近 ...
- 常用的code snipper
Xcode 10.2.1 版本,自动代码提示功能延迟很大,很多情况下代码提示甚至会无效,但是code snippet 唤起的响应很快,从提高效率的情况考虑,即使系统提供的代码提示制作成code sni ...
- json字符串转List集合
public List<Map<String,PendingInfo>> jsonToList(String json){//PendingInfo可以换成其它bean类 Li ...
- Vue全局组件创建三种方法
<my-com1></my-com1> <my-com2></my-com2> <template id="tmp1"> ...
- 001_C语言中运算符的优先级
总的来说就是: 1. 最高:单目运算符(() > * 解引用,&取地址,-取相反数,++等自增(或减)运算,!取反运算...); 2. 次之:双目运算符(算数运算符 > 移位运算符 ...
- iOS开发添加新手引导
往往项目中经常出现此类需求 用户通过点击引导按钮可响应页面附带按钮的点击事件. // // gzhGuideView.h // GuideView // // Created by 郭志贺 on 20 ...
- 分布式项目开发-spring-dao.xml基础配置
基础步骤: 1 数据源 2 sqlSessionFactory 3 MapperScan 打包. db.properties文件 db.username=root db.password=123456 ...
- mysql去重复关键字distinct的用法
distinct的去重复的提前是表中所有列的数据完成相同时,才能把相同的数据只保留一条,并不是 distinct 列名,除去某一列相同的数据,并且 distinct要放在第一个列前面.案例如下:一个学 ...
- burpsuite 2.0beta体验
这里有破解版:http://ximcx.cn/post-110.html 一直再用1.7x版本,2.0的还没怎么用过 移除了 Scanner 和spider 选项卡,全部整理到Dashboard里 代 ...
- python winreg总结
注册表 结构 注册表由键(key,或称“项”).子键(subkey,子项)和值项(value)构成.一个键就是树状数据结构中的一个节点,而子键就是这个节点的子节点,子键也是键.一个值项则是一个键的一条 ...