题目传送门

https://lydsy.com/JudgeOnline/problem.php?id=1195

题解

建立 AC 自动机,然后构建出 trie 图。

然后直接在 trie 图上走。但是我们需要经过每一个串。

所以我们处理一下每个点代表了哪些串,然后把状态加入进 bfs 状态。

然后 bfs 就可以了。


\(O(n)\)。

#include<bits/stdc++.h>

#define fec(i, x, y) (int i = head[x], y = g[i].to; i; i = g[i].ne, y = g[i].to)
#define dbg(...) fprintf(stderr, __VA_ARGS__)
#define File(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)
#define fi first
#define se second
#define pb push_back template<typename A, typename B> inline char smax(A &a, const B &b) {return a < b ? a = b, 1 : 0;}
template<typename A, typename B> inline char smin(A &a, const B &b) {return b < a ? a = b, 1 : 0;} typedef long long ll; typedef unsigned long long ull; typedef std::pair<int, int> pii; template<typename I> inline void read(I &x) {
int f = 0, c;
while (!isdigit(c = getchar())) c == '-' ? f = 1 : 0;
x = c & 15;
while (isdigit(c = getchar())) x = (x << 1) + (x << 3) + (c & 15);
f ? x = -x : 0;
} const int N = 12 + 1;
const int M = 50 + 1;
const int NM = 12 * 50 + 1;
const int NP = (1 << 12);
const int NMP = 12 * 50 * ((1 << 12) - 1) + 1; int n, m, nod;
int q[NMP], q2[NMP], fr[NM][NP];
char s[N], ans[NM];
struct Node { int c[26], fa, v; char s; } t[NM]; inline void ins(char *s, int id) {
int n = strlen(s + 1), o = 0;
for (int i = 1; i <= n; ++i) {
if (!t[o].c[s[i] - 'A']) t[o].c[s[i] - 'A'] = ++nod, t[nod].s = s[i];
o = t[o].c[s[i] - 'A'];
}
t[o].v |= 1 << (id - 1);
}
inline void build() {
int hd = 0, tl = 0;
for (int i = 0; i < 26; ++i) if (t[0].c[i]) q[++tl] = t[0].c[i];
while (hd < tl) {
int x = q[++hd]; t[x].v |= t[t[x].fa].v;
for (int i = 0; i < 26; ++i)
if (t[x].c[i]) t[t[x].c[i]].fa = t[t[x].fa].c[i], q[++tl] = t[x].c[i];
else t[x].c[i] = t[t[x].fa].c[i];
}
} inline void work() {
int hd = 0, tl = 1, S = (1 << n) - 1;
q[tl] = 0, q2[tl] = 0, fr[0][0] = -1;
while (hd < tl) {
int x = q[++hd];
int s = q2[hd];
// dbg("x = %d, s = %d\n", x, s);
for (int i = 0; i < 26; ++i) if (t[x].c[i]) {
int y = t[x].c[i], ss = s | t[y].v;
// dbg("y = %d, ss = %d\n", y, ss);
if (!fr[y][ss]) {
fr[y][ss] = hd, q[++tl] = y, q2[tl] = ss;
// dbg("****** y = %d, ss = %d\n", y, ss);
if (ss == S) {
int len = 0, z = y, zs = ss, zz;
while (~fr[z][zs]) ans[++len] = t[z].s, zz = fr[z][zs], z = q[zz], zs = q2[zz];
while (len) putchar(ans[len--]);
puts("");
// dbg("*********\n");
return;
}
assert(fr[y][ss]);
}
}
}
} inline void init() {
read(n);
for (int i = 1; i <= n; ++i) scanf("%s", s + 1), ins(s, i);
build();
// dbg("*************\n");
} int main() {
#ifdef hzhkk
freopen("hkk.in", "r", stdin);
#endif
init();
work();
fclose(stdin), fclose(stdout);
return 0;
}

bzoj1195 [HNOI2006]最短母串 AC 自动机+状压+bfs的更多相关文章

  1. [HNOI2006]最短母串 (AC自动机+状压)

    Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. Input 第一行是一个正整数n(n<=12) ...

  2. BZOJ 1195: [HNOI2006]最短母串 AC自动机+状压+搜索

    思路比较直接. 由于 $n$ 很小,直接定义 $f[i][j]$ 表示当前在自动机中的节点 $i,$ 被覆盖串的集合为 $j$ 的方案数. #include <bits/stdc++.h> ...

  3. BZOJ1195[HNOI2006]最短母串——AC自动机+BFS+状态压缩

    题目描述 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. 输入 第一行是一个正整数n(n<=12),表示给定的字符串的 ...

  4. 【bzoj1195】[HNOI2006]最短母串 AC自动机+状态压缩+BFS最短路

    原文地址:http://www.cnblogs.com/GXZlegend/p/6825226.html 题目描述 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串 ...

  5. BZOJ1195 [HNOI2006]最短母串 AC自动机 bfs

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 传送门 - BZOJ1195 题意概括 给出一堆串,然后求一个包含这些串的所有串的最短的中的字典序最小的. 题解 先造一个AC ...

  6. Bzoj1195 [HNOI2006]最短母串 [AC自动机]

    Time Limit: 10 Sec  Memory Limit: 32 MBSubmit: 1304  Solved: 439 Description 给定n个字符串(S1,S2,„,Sn),要求找 ...

  7. BZOJ 1195 [HNOI2006]最短母串 (Trie图+状压+bfs最短路)

    BZOJ1195 LOJ10061 题目大意:给你$n$个模式串,求一个最短且字典序最小的文本串并输出这个串,$n<=12,len<=50$ 首先对所有模式串构造$Trie$图,$Trie ...

  8. BZOJ_1195_[HNOI2006]最短母串_AC自动机+BFS+分层图

    BZOJ_1195_[HNOI2006]最短母串_AC自动机+BFS+分层图 Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2, ...

  9. [bzoj1195][HNOI2006]最短母串_动态规划_状压dp

    最短母串 bzoj-1195 HNOI-2006 题目大意:给一个包含n个字符串的字符集,求一个字典序最小的字符串使得字符集中所有的串都是该串的子串. 注释:$1\le n\le 12$,$1\le ...

随机推荐

  1. C++ STL 关于双向链表list的splice函数

    转载自https://blog.csdn.net/qjh5606/article/details/85881680 list::splice实现list拼接的功能.将源list的内容部分或全部元素删除 ...

  2. HTML和JS完成页面点击四个角弹出管理页面

    实现方法1: HTML代码: <div class="top-left-corner"></div> <div class="top-rig ...

  3. org.hibernate.AssertionFailure: null id don't flus

    我的是字段编码和数据库不匹配,是爬的微博数据

  4. laravel 中 同个主域名下,多个项目共享session登录状态

    共享session的前提是session在一个公共的地方,比如database,redis等,laravel框架提供了很大驱动选择: 这里只需要在配置文件里配置三个地方即可 'driver' => ...

  5. c++ 调用 sqlcipher

    #include <iostream> #include <string.h> #include "sqlite3.h" using namespace s ...

  6. 常用获取Android崩溃日志和IOS崩溃日志的几种方法

    一:前言 在日常测试app时,经常会遇到崩溃问题,测试快速抓取到崩溃日志可以有效方便开发进行定位,快速解决问题所在测试做到测试分析,定位是非常重要的,这也是判断一个测试能力指标的一大维度. 二:And ...

  7. UVA11987 带删除并查集

    1~n,n个数,初始每个数独自作为一个集合,然后进行m次操作.操作有三种:1 p q :把 p 所在的集合合并到 q 所在的集合 2 p q :把 p 从 p 的集合中拿出,放到 q 的集合里 3 p ...

  8. 【Windows Server存储】MBR和GPT分区表

    MBR和GPT分区表 分区表用于引导操作系统 master boot record(MBR)于1983年首次在PC上推出 最大4个主分区 2太空间 GUID Partition Table(GPT), ...

  9. 解读Nodejs多核处理模块cluste

    http://blog.fens.me/nodejs-core-cluster/ Node.js开发框架Express4.x   http://blog.fens.me/nodejs-express4 ...

  10. [转帖]linux screen 命令详解,xshell关掉窗口或者断开连接,查看断开前执行的命令

    linux screen 命令详解,xshell关掉窗口或者断开连接,查看断开前执行的命令 https://binwaer.com/post/12.html yun install -y screen ...