Description

给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串。

Input

第一行是一个正整数n(n<=12),表示给定的字符串的个数。
以下的n行,每行有一个全由大写字母组成的字符串。每个字符串的长度不超过50.

Output

只有一行,为找到的最短的字符串T。在保证最短的前提下,
如果有多个字符串都满足要求,那么必须输出按字典序排列的第一个。

Sample Input

2
ABCD
BCDABC

Sample Output

ABCDABC

拿这题练了练数组版的AC自动机

数据范围显然状压 插入时预处理出每个节点是哪个串的结束节点

然后建图 连fail指针的时候合并状态

为了最短显然需要按层转移,所以bfs

可以保证一达到末状态就return得到最优解

数组

#include<queue>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
using namespace std;
int n,tot=;
char s[];
struct trie
{
int son[],st,fail;
}t[];
void ins(char* str,int k)
{
int l=strlen(str+),root=;
for(int i=;i<=l;i++)
{
int x=str[i]-'A';
if(!t[root].son[x])t[root].son[x]=++tot;
root=t[root].son[x];
}
t[root].st|=<<(k-);
}
void build()
{
queue<int> q;
for(int i=;i<;i++)
if(t[].son[i])q.push(t[].son[i]);
while(!q.empty())
{
int x=q.front();
q.pop();
for(int i=;i<;i++)
{
int &y=t[x].son[i];
if(!y)
{
y=t[t[x].fail].son[i];
continue;
}
t[y].fail=t[t[x].fail].son[i];
t[y].st|=t[t[y].fail].st;
q.push(y);
}
}
}
bool v[][(<<)+];
int let[(<<)+],fa[(<<)+],ans[],num=;
void bfs()
{
queue<pair<int,int> > q;
q.push(make_pair(,));
int f=,ss=;
while(!q.empty())
{
int x=q.front().first,nowst=q.front().second;
q.pop();
if(nowst==(<<n)-)
{
for(int i=f;i;i=fa[i])
ans[++num]=let[i];
for(int i=num;i;i--)putchar(ans[i]+'A');
return ;
}
for(int i=;i<;i++)
{
int y=t[x].son[i],nxtst=nowst|t[y].st;
if(!v[y][nxtst])
{
v[y][nxtst]=;
ss++;
fa[ss]=f;
let[ss]=i;
q.push(make_pair(y,nxtst));
}
}
f++;
}
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%s",s+);
ins(s,i);
}
build();
bfs();
return ;
}

指针

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdlib>
using namespace std;
const int N=;
int n;
char s[N];
struct node
{
node *son[];
int st;
bool vis[(<<)+];
node *fail;
node()
{
memset(this,,sizeof(node));
}
};
node *root;
void ini()
{
root=new node();
}
void ins(char *str,int num)
{
int l=strlen(str+);
node *now=root;
for(int i=;i<=l;i++)
{
if(!now->son[str[i]-'A'])now->son[str[i]-'A']=new node();
now=now->son[str[i]-'A'];
}
now->st|=<<(num-);
} void build()
{
queue<node*>q;
for(int i=;i<;i++)
{
if(root->son[i])
{
root->son[i]->fail=root;
q.push(root->son[i]);
}
else root->son[i]=root;
}
while(!q.empty())
{
node *x=q.front();
q.pop();
for(int i=;i<;i++)
{
if(x->son[i])
{
x->son[i]->fail=x->fail->son[i];
if(x->son[i]->fail)x->son[i]->st|=x->son[i]->fail->st;
q.push(x->son[i]);
}
else x->son[i]=x->fail->son[i];
}
}
}
int fa[],ans[],tot=,qwq[];
void bfs()
{
queue<node*> q;
queue<int> ST;
q.push(root);ST.push();
root->vis[]=;
int f=,ss=;
while(!q.empty())
{
node *x=q.front();int nowSt=ST.front();
q.pop();ST.pop();
// cout<<(x->st)<<endl;
if(nowSt==(<<n)-)
{
for(int i=f;i;i=fa[i])ans[++tot]=qwq[i];
for(int i=tot;i;i--)putchar(ans[i]+'A');
return ;
}
for(int i=;i<;i++)
{
if(!x->son[i])continue;
int state=nowSt|(x->son[i]->st);
if(!x->son[i]->vis[state])
{
x->son[i]->vis[state]=;
ss++;
fa[ss]=f;
qwq[ss]=i;
q.push(x->son[i]);
ST.push(state);
}
}
f++;
}
}
int main()
{
scanf("%d",&n);
ini();
for(int i=;i<=n;i++)
{
scanf("%s",s+);
ins(s,i);
}
build();
bfs();
return ;
}

(话说这题数组大小神TM坑啊……)

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

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

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=1195 题解 建立 AC 自动机,然后构建出 trie 图. 然后直接在 trie 图上走.但是 ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. Mariadb galera 集群

    部署galera 多主架构 (galera集群多用于关键性业务,因为galera集群为了数据的一致性,采用的是同步的机制,这就使galera牺牲了一部分性能来换取数据一致性.) 环境准备:三台服务器 ...

  2. 用JAVA生成老电影海报

    先看图,再讲原理.生成效果对照: 机器全自己主动生成.是不是非常酷炫?:) 数字图像,由无数个像素组成,通常情况下,每一个像素包括有RGB三个值,算法原理事实上非常easy: 一,遍历全部像素,将RG ...

  3. web 开发之js---js 中的定时器setTimeout(function,time),setinterval(function,time)

    ####10秒自动跳转 <div class="jf_register"> <h2>您好,欢迎光临<fmt:message key="b2c ...

  4. iOS开发——高级篇——Runtime实际应用

    前言 本篇主要介绍Runtime在开发中的一些使用场景,顺便讲解了下MJExtension的底层实现 一.runtime简介 RunTime简称运行时.OC就是运行时机制,也就是在运行时候的一些机制, ...

  5. 经典的printk 写法

    经典的printk 写法: printk("[lynn--%s@%d]: addr:0x%x  \n",__func__,__LINE__,obj->client->a ...

  6. MPMoviePlayerController属性方法简介

    属性 说明 @property (nonatomic, copy) NSURL *contentURL 播放媒体URL,这个URL可以是本地路径,也可以是网络路径 @property (nonatom ...

  7. 【POI2007】【Bzoj 1103】大都市meg

    http://www.lydsy.com/JudgeOnline/problem.php?id=1103 在线查询某点到根节点的点权和,参考DFS序&欧拉序列,用树状数组维护即可O(nlogn ...

  8. mysql与mongoDB的特点和优劣

    首先分析下mysql与mongoDB的特点和优劣 从图中分析: 再来分析下应用场景: a.如果需要将mongodb作为后端db来代替mysql使用,即这里mysql与mongodb 属于平行级别,那么 ...

  9. bzoj 3498: PA2009 Cakes【瞎搞】

    参考:https://www.cnblogs.com/spfa/p/7495438.html 为什么邻接表会TTTTTTTLE啊...只能用vector? 把点按照点权从大到小排序,把无向边变成排名靠 ...

  10. sql server 触发器详细应用

    SQL Server 触发器 触发器是一种特殊类型的存储过程,它不同于之前的我们介绍的存储过程.触发器主要是通过事件进行触发被自动调用执行的.而存储过程可以通过存储过程的名称被调用.  Ø 什么是触发 ...