2782: [HNOI2006]最短母串

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 3  Solved: 2
[Submit][Status][Web Board]

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

HINT

 

Source

题解:

  

  首先我的思路十分傻叉,是f[i][j][k]f[i][j][k]表示长度为ii,在自动机上的节点为jj,包含子串的状态为kk可不可能.但这样复杂度直接爆炸.

  但是我们可以令f[i][j]f[i][j]表示在自动机上的节点为ii,包含子串的状态为jj时的最短长度.

  这样我们就转化成了边权均为1的单源最短路,BFS就行了.

  若按照字母字典序从小到大的顺序进行BFS,得出的就是字典序最小的答案了.

  (有点卡内存)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int inf=1e9;
struct Node{
int fail,ch[],val;
void clear(){
fail=val=;
memset(ch,,sizeof(ch));
}
}tr[];
int sz;
int bin[],n;
void insert(char *s,int val){
int u=,len=strlen(s);
for(int i=;i<len;i++){
int c=s[i]-'A';
if(!tr[u].ch[c]){
tr[u].ch[c]=++sz;
tr[sz].clear();
}
u=tr[u].ch[c];
}
tr[u].val|=bin[val];
}
void build(){
queue<int>q;q.push();
while(!q.empty()){
int u=q.front();q.pop();
for(int i=;i<;i++){
if(tr[u].ch[i]){
int v=tr[u].ch[i];
if(u)tr[v].fail=tr[tr[u].fail].ch[i];
q.push(v);
}else tr[u].ch[i]=tr[tr[u].fail].ch[i];
}
}
}
int fromu[][],froms[][];
bool vis[][];
void print(int u,int s){
if(!u)return;
print(fromu[u][s],froms[u][s]);
for(int i=;i<;i++){
int v=tr[fromu[u][s]].ch[i],t=froms[u][s];
for(int p=v;p;p=tr[p].fail)
t|=tr[p].val;
if(v==u&&t==s){
putchar('A'+i);
break;
}
}
}
void bfs(){
queue<int>q1,q2;
q1.push();q2.push();
vis[][]=;
while(!q1.empty()){
int u=q1.front(),s=q2.front();q1.pop();q2.pop();
for(int i=;i<;i++){
int v=tr[u].ch[i],t=s;
for(int p=v;p;p=tr[p].fail)
t|=tr[p].val;
if(!vis[v][t]){
vis[v][t]=;
q1.push(v);q2.push(t);
fromu[v][t]=u;
froms[v][t]=s;
if(t==bin[n+]-){
print(v,t);
return;
}
}
}
}
}
char s[];
int main(){
scanf("%d",&n);
tr[sz=].clear();
bin[]=;
for(int i=;i<;i++)bin[i]=bin[i-]<<;
for(int i=;i<=n;i++){
scanf("%s",s);
insert(s,i);
}
build();
bfs();
return ;
}
 

2782: [HNOI2006]最短母串的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  9. bzoj 1195 [HNOI2006]最短母串 bfs 状压 最短路 AC自动机

    LINK:最短母串 求母串的问题.不适合SAM. 可以先简化问题 考虑给出的n个字符串不存在包含关系. 那么 那么存在的情况 只可能有 两个字符串拼接起来能表示另外一个字符串 或者某个字符串的后缀可以 ...

随机推荐

  1. U3D脚本开发基础

    1.MonoBehaviour类,定义了对各种特定事件的脚本响应函数.这些函数均以On做开头. 2.U3D中常用的组件及对应变量名如下: Transform(transform),Rigidbody( ...

  2. PAT1064(上)分析部分

    Complete Binary Search Tree (30) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 16000 B A Binary Search Tree (BST) ...

  3. list实例应用

    Java代码如下: package Test01; import java.util.ArrayList; import java.util.List; public class Test02 { p ...

  4. UIView(包括子类)的几个初始化时执行动作的时机

    转载自:http://www.tqcto.com/article/mobile/56963.html 根据你需要执行的动作, 这里有几个方法: -(id)initWithFrame:(CGRect)f ...

  5. 可信执行环境TEE(转)

    硬件威胁:ARM的架构设计 软件威胁 TEE是中等安全级别 可信执行环境(TEE)是Global Platform(GP)提出的概念.针对移动设备的开放环境,安全问题也越来越受到关注,不仅仅是终端用户 ...

  6. SDAU课程练习--problemB(1001)

    题目描述 There is a pile of n wooden sticks. The length and weight of each stick are known in advance. T ...

  7. Qt5:无边框窗口拖动

    在窗口程序中,无边框窗口程序一般需要特殊处理才能拖动 Qt中,要实现无边框窗口的拖动,需要重新实现 mousePressEvent 和 mouseMoveEvent 俩虚函数 void Widget: ...

  8. memory runs at single channel问题解决

    memory runs at single channel 解决方案:开机后按DEL ,然后进入BIOS 选择第一项,回车! advanced下面的有个momori什么什么的,选择disable. m ...

  9. 单源最短路-dijkstra算法(未优化)

    bool used[maxn]; int g[maxn][maxn]; // 边未联系的填充为INF int d[maxn]; void dijkstra(int s){ memset(g,false ...

  10. oracle 主键自动增长

    oracle 主键自动增长 2009-12-11 16:07:00|  分类: 数据库资料|字号 订阅     这几天搞Oracle,想让表的主键实现自动增长,查网络实现如下: create tabl ...