@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 倍。

最新文章

  1. Linux安装卸载Mysql数据库
  2. VSS 的修复和扫描
  3. python模块及包的导入
  4. Android学习笔记(十一)——ListView的使用(下)
  5. [转] - MC、MC、MCMC简述
  6. projecteuler Problem 9 Special Pythagorean triplet
  7. hihocode ---1032
  8. iOS:实现MKAnnotation协议,在地图上设置大头针,点击显示具体的位置信息
  9. 读书笔记-详解C程序开发中 .c和.h文件的区别
  10. android 各种xml的作用
  11. C# 零散笔记
  12. java编程接口(5) ------ button和button组
  13. WebDriver获取table的内容(通过动态获取Table单元格的TagName对其innerHTML值进行获取)
  14. js Web存储方式
  15. Flask 学习 五 电子邮件
  16. [SDOI2017]数字表格
  17. 记录MYSQL中SQL语句的一个坑.
  18. [Hive_add_7] Hive 实现最高气温统计
  19. vue前端框架面试问题汇总
  20. spring boot 解决跨域访问

热门文章

  1. mysql小白系列_08 zabbix3.2.6概念及部署
  2. Python小技巧:如何批量更新已安装的库?
  3. 【python爬虫】scrapy入门6-生成多个spider
  4. ubuntu 安装 swftoos
  5. MySQL性能分析(Explain)
  6. Network Motif 文献调研
  7. Java—JSON串转换成实体Bean对象模板
  8. [Objective-C] 006_Protocol(协议)
  9. Java中的集合(七)双列集合顶层接口------Map接口架构
  10. C# 根据BackgroundWoker异步模型和ProgressBar控件,自定义进度条控件