题面:洛谷

题解:

  如果我们对这些小串建出AC自动机,那么我们所求的大串就是要求满足遍历过所有AC自动机上的叶子节点,且经过步数最少的串。如果有多个步数相同的串,要输出字典序最小的串。

  在AC自动机上DP。

  因为我们要求所求串内要出现所有给定小串,而小串个数较少,因此我们考虑状压,然后保存下val[i]表示走到这个点,就可以拥有哪些子串。因为一个非终止节点也可能包含给定小串,因此我们要在建好fail之后,继承一个点x的fail[x]所包含的小串,按编号大小更新即可保证在x被更新之前fail[x]已经被更新。

  设f[i][j]表示在AC自动机的第i个节点上,状态为j的最小代价。

  不知你是否注意到这个状态里没有限制长度和字典序?

  其实这是因为我们可以用bfs解决问题,因为走任意一步的代价都是1,也就是每条边的权值都是1,所以如果我们用bfs的顺序来DP,那么谁先DP到拥有所有串,谁就是代价最小的方案。

  那么怎么保证字典序最小?

  我们只需要在bfs的时候从'a'开始枚举即可。

  

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 610
#define ac 4596
#define inf 2139062143 int n, m, maxn, tmp, head, tail;
int f[AC][ac], q1[AC * ac], q2[AC * ac];
short l1[AC][ac], l2[AC][ac];
int c[AC][], val[AC], fail[AC], go[AC], tot;
char s[AC]; inline void add()
{
int len = strlen(s + ), now = ;
for(R i = ; i <= len; i ++)
{
int v = s[i] - 'A';
if(!c[now][v]) c[now][v] = ++ tot, go[tot] = v;
now = c[now][v];
}
val[now] |= tmp, tmp <<= ;//还是要|= 的,否则要是有多个相同串在同一个节点结束就不好了,,,,
} #define q q1
void build()
{
for(R i = ; i < ; i ++)
if(c[][i]) q[++ tail] = c[][i];
while(head < tail)
{
int x = q[++ head];
for(R i = ; i < ; i ++)
{
if(c[x][i]) fail[c[x][i]] = c[fail[x]][i], q[++ tail] = c[x][i];
else c[x][i] = c[fail[x]][i];
}
}
for(R i = ; i <= tot; i ++) val[i] |= val[fail[i]];
}
#undef q void pre()
{
scanf("%d", &n);
maxn = ( << n) - , tmp = ;
memset(f, , sizeof(f));
for(R i = ; i <= n; i ++) scanf("%s", s + ), add();
} void bfs()
{
head = tail = ;
q1[++ tail] = , q2[tail] = ;
f[][] = ;
while(head < tail)
{
int x = q1[++ head], sta = q2[head];
if(sta == maxn)
{
head = ;
while(x)
{
q1[++ head] = go[x];
int tmp1 = x, tmp2 = sta;
x = l1[tmp1][tmp2], sta = l2[tmp1][tmp2];
}//因为要用2次,但是用了第一次之后x or sta就改变了,所以必须保存到临时变量
for(R i = head; i; i --) printf("%c", q1[i] + 'A');
return ;
}
for(R i = ; i < ; i ++)
{
int v = c[x][i], w = sta | val[v];
if(f[v][w] == inf) //bfs包括了最短和字典序最小
{
q1[++ tail] = v, q2[tail] = w;
f[v][w] = f[x][sta] + ;
l1[v][w] = x, l2[v][w] = sta;
}
}
}
} int main()
{
// freopen("in.in", "r", stdin);
pre();
build();
bfs();
// fclose(stdin);
return ;
}

[HNOI2006]最短母串问题 AC自动机的更多相关文章

  1. [HNOI2006]最短母串问题 --- AC自动机 + 隐式图搜索

    [HNOI2006]最短母串问题 题目描述: 给定n个字符串(S1,S2.....,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,......,Sn)都是T的子串. 输入格式: 第 ...

  2. [BZOJ1195]:[HNOI2006]最短母串(AC自动机+BFS)

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

  3. [HNOI2006]最短母串问题——AC自动机+状压+bfs环形处理

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

  4. P2322 [HNOI2006]最短母串问题

    P2322 [HNOI2006]最短母串问题 AC自动机+bfs 题目要求:在AC自动机建的Trie图上找到一条最短链,包含所有带结尾标记的点 因为n<12,所以我们可以用二进制保存状态:某个带 ...

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

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

  6. 【状态压缩dp】1195: [HNOI2006]最短母串

    一个清晰的思路就是状压dp:不过也有AC自动机+BFS的做法 Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T ...

  7. bzoj 1195: [HNOI2006]最短母串 爆搜

    1195: [HNOI2006]最短母串 Time Limit: 10 Sec  Memory Limit: 32 MBSubmit: 894  Solved: 288[Submit][Status] ...

  8. 2782: [HNOI2006]最短母串

    2782: [HNOI2006]最短母串 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 3  Solved: 2[Submit][Status][Web ...

  9. BZOJ 1195: [HNOI2006]最短母串

    1195: [HNOI2006]最短母串 Time Limit: 10 Sec  Memory Limit: 32 MBSubmit: 1346  Solved: 450[Submit][Status ...

随机推荐

  1. 解决 idea template jsp模板中使用自定义路径 模板不显示问题

    ${} 是一个模板中的关键字,所以建立时需要用 \ 注释即可正常显示  ${APP_PATH}

  2. 安装完.net core sdk 后部署 ASP.NET Core 出现错误502.5

    将项目升级到和sdk一样的版本 然后 命令行执行 iisreset

  3. tensorflow中tensor与数组之间的转换

    # 主要是两个方法: # 1.数组转tensor:数组a, tensor_a=tf.convert_to_tensor(a) # 2.tensor转数组:tensor b, array_b=b.eva ...

  4. python序列和其它类型的比较

    序列对象可以与相同类型的其他对象比较.它们使用 字典顺序 进行比较:首先比较两个python序列的第一个元素,如果不同,那么这就决定了比较操作的结果.如果它们相同,就再比较每个序列的第二个元素,以此类 ...

  5. mui搜索框 搜索点击事件

    <div class="mui-input-row mui-search"> <input type="search" class=" ...

  6. Python3 解压序列

    一 普遍情况: x,y,z = 1,2,3 print("x:",x) # x:1 print("y:",y) # y:2 print("z:&quo ...

  7. OOP 1.3 动态内存分配

    1.new运算符用法 分配一个变量:P=new T; T是任意类型名,P是类型为T的指针.动态分配出一片大小为sizeof(T)字节的内存空间,将该空间的起始地址赋值给P(new T的返回值为 T). ...

  8. 【IdentityServer4文档】- 使用客户端凭据保护 API

    使用客户端凭据保护 API quickstart 介绍了使用 IdentityServer 保护 API 的最基本场景. 接下来的场景,我们将定义一个 API 和一个想要访问它的客户端. 客户端将在 ...

  9. Android工程方法数超过64k,The number of method references in a .dex file cannot exceed 64K.

    最近将一个老的Eclipse项目转到Android Studio后,用gradle添加了几个依赖,项目可以make,但是一旦run就报错 Error:The number of method refe ...

  10. IOC与DI(xml 配置)

    Spring可以帮助我们管理软件开发过程中的对象,以及如何创建和维护对象之间的关系. Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,可以将组建的耦合度降至最低,即实现解耦 ...