BZOJ1195 LOJ10061

题目大意:给你$n$个模式串,求一个最短且字典序最小的文本串并输出这个串,$n<=12,len<=50$

首先对所有模式串构造$Trie$图,$Trie$图的性质和$DP$的性质简直是完美契合..

模式串数量很少,考虑状压

定义$f[x][s]$表示现在所在$Trie$图内的位置为$x$,已经匹配到的串的状态为$s$,此时需要文本串的最短长度

转移十分显然,$f[fail_{x}][s|ed[fail_{x}])]=min(f[x][s])+1$

最后找出最小的$f[x][(1<<n)-1]$

然而...直接这样转移我们没办法统计答案啊

考虑把问题放到图上,利用$bfs$队列先进先出的性质,如果我们优先把字典序小的状态推进队列,再通过记录当前状态第一次被更新时的上一层状态$fa[..]$的方式记录路径,跑$bfs$最短路,当队列中出现$s==(1<<n)-1$时立即结束,此时我们求得的一定是长度最短且字典序最小的答案!

注意可能有相同的串

注意不要忘了建$fail$树,如果某个节点是某个串的结尾,也要把它是这个串的结尾的信息传递到它在$fail$树中的子树中去!我没传竟然还有70分

 #include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define NN 610
#define MM 4100
#define ll long long
#define uint unsigned int
#define ull unsigned long long
#define inf 0x3f3f3f3f
#define idx(x) (x-'A')
using namespace std; int n,cte;
int head[NN];
char str[NN];
struct Edge{int to,nxt;}edge[NN*];
void ae(int u,int v){
cte++;edge[cte].nxt=head[u];
edge[cte].to=v,head[u]=cte;
}
struct node{
int x,s;
node(int x,int s):x(x),s(s){}
node(){}
}fa[NN][MM];
int dis[NN][MM];
namespace AC{
int ch[NN][],fail[NN],ed[NN],val[NN],tot;
void Build_Trie(char *str,int len,int id)
{
int x=;
for(int i=;i<=len;i++){
if(!ch[x][idx(str[i])])
ch[x][idx(str[i])]=++tot,val[tot]=idx(str[i]);
x=ch[x][idx(str[i])];
}ed[x]|=(<<(id-));
}
void Build_Fail()
{
queue<int>q;
for(int i=;i<;i++)
if(ch[][i]) q.push(ch[][i]);
while(!q.empty())
{
int x=q.front();q.pop();
ae(fail[x],x);
for(int i=;i<;i++)
{
if(ch[x][i]){
fail[ch[x][i]]=ch[fail[x]][i];
q.push(ch[x][i]);
}else{
ch[x][i]=ch[fail[x]][i];
}
}
}
q.push();
while(!q.empty())
{
int x=q.front();q.pop();
for(int j=head[x];j;j=edge[j].nxt){
int v=edge[j].to;
ed[v]|=ed[x];
q.push(v);
}
}
}
node Bfs()
{
queue<node>q;
memset(dis,0x3f,sizeof(dis));
q.push(node(,));
dis[][]=;
node k1,k2;
int x,v,s,t;
while(!q.empty())
{
k1=q.front();q.pop();
x=k1.x,s=k1.s;
if(s==(<<n)-) return k1;
for(int i=;i<;i++)
{
v=ch[x][i],t=s|ed[v];
if(dis[v][t]>dis[x][s]+){
dis[v][t]=dis[x][s]+;
fa[v][t]=k1;
q.push(node(v,t));
}
}
}
/*for(int i=1;i<=tot;i++)
printf("%d:%d\n",i,dis[i][(1<<n)-1]);*/
}
char Ans[NN];
void solve()
{
for(int i=;i<=n;i++){
scanf("%s",str+);
int len=strlen(str+);
Build_Trie(str,len,i);}
Build_Fail();
node ans=Bfs();
node a=ans;
int num=;
while(a.x||a.s){
Ans[++num]=val[a.x]+'A';
a=fa[a.x][a.s];}
for(int i=num;i>;i--)
printf("%c",Ans[i]);
puts("");
}
}; int main()
{
//freopen("t2.in","r",stdin);
scanf("%d",&n);
AC::solve();
return ;
}

BZOJ 1195 [HNOI2006]最短母串 (Trie图+状压+bfs最短路)的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

  7. 【刷题】BZOJ 1195 [HNOI2006]最短母串

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

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

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

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

    我有病吧--明明直接枚举是否匹配就可以非要写hash,然后果然冲突了(--我个非酋居然还敢用hash 设f[s][i]为已选串状态为s并且最后一个串是i,还有预处理出g[i][j]表示最长有长为g[i ...

随机推荐

  1. 在使用easyui datagrid在tab中遇到的问题

    当切换tab时,数据加载了,但是table的宽和高不能不能够初始化. 郁闷了好久解决了这个问题: 在页面加载时和切换tab时,获取当前tab的名字,进行内容的初始化 $('a[name="m ...

  2. linux内存随笔

    内存在电脑中使用广泛,比如内存条内存.显卡显存.cpu缓存.raid卡缓存等,缓存就是数据交换的缓冲区(称作cache),缓存往往都是RAM(断电文件丢失),他们的读写速率非常高,用来帮助硬件更快的响 ...

  3. Vue系列(三):组件及数据传递、路由、单文件组件、vue-cli脚手架

    上一篇:Vue系列(二):发送Ajax.JSONP请求.Vue生命周期及实例属性和方法.自定义指令与过渡 一. 组件component 1. 什么是组件? 组件(Component)是 Vue.js ...

  4. 阿里云Linux系统Nginx配置多个域名的方法

    Nginx绑定多个域名,可通过把多个域名规则写一个配置文件里实现,也可通过分别建立多个域名配置文件实现,为了管理方便,建议每个域名建一个文件,有些同类域名则可写在一个总的配置文件里. 1. 比如我想建 ...

  5. Jenkins学习总结(5)——免费DevOps开源工具简介

    一:开发工具 1.版本控制系统 Git Git是一个开源的分布式版本控制系统,用以有效.高速的处理从很小到非常大的项目版本管理. 2.代码托管平台 GitLab GitLab是一个利用Ruby on ...

  6. HDU 2512

    水题 #include <iostream> #include <cstdio> #include <algorithm> #define LL __int64 # ...

  7. 字符串的HashCode可能相同

    字符串的HashCode可能相同 学习了:http://blog.csdn.net/hl_java/article/details/71511815

  8. 关闭 sftp

    vi /etc/ssh/sshd_config 注释掉这行Subsystem  sftp    /usr/libexec/openssh/sftp-server /etc/rc.d/init.d/ss ...

  9. shareSDK的初步使用(shareSDK中微信、qq等兼容问题,以及cocoapods支持架构冲突问题的解决)

    第一次使用shareSDK来做第三方分享,可是.昨天一天都是在调试bug,一直错误不断! 先说下我的开发环境: xcode:5.1 真机调试:iPhone5s 我们都知道xcode5.1以后開始是支持 ...

  10. centos6高速部署java应用

    眼下提供IDC服务的厂商真的是五花八门,可是更正服务到位的却为数不多,搞得比較好的应该是阿里云.天成.51idc,出于时间考虑还是建议选用windows,至少安装开发环境会方便得多,不会耗费太长时间. ...