BZOJ 1195 [HNOI2006]最短母串 (Trie图+状压+bfs最短路)
题目大意:给你$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最短路)的更多相关文章
- BZOJ 1195: [HNOI2006]最短母串 AC自动机+状压+搜索
思路比较直接. 由于 $n$ 很小,直接定义 $f[i][j]$ 表示当前在自动机中的节点 $i,$ 被覆盖串的集合为 $j$ 的方案数. #include <bits/stdc++.h> ...
- bzoj1195 [HNOI2006]最短母串 AC 自动机+状压+bfs
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=1195 题解 建立 AC 自动机,然后构建出 trie 图. 然后直接在 trie 图上走.但是 ...
- bzoj 1195: [HNOI2006]最短母串 爆搜
1195: [HNOI2006]最短母串 Time Limit: 10 Sec Memory Limit: 32 MBSubmit: 894 Solved: 288[Submit][Status] ...
- BZOJ 1195: [HNOI2006]最短母串
1195: [HNOI2006]最短母串 Time Limit: 10 Sec Memory Limit: 32 MBSubmit: 1346 Solved: 450[Submit][Status ...
- bzoj 1195 [HNOI2006]最短母串 bfs 状压 最短路 AC自动机
LINK:最短母串 求母串的问题.不适合SAM. 可以先简化问题 考虑给出的n个字符串不存在包含关系. 那么 那么存在的情况 只可能有 两个字符串拼接起来能表示另外一个字符串 或者某个字符串的后缀可以 ...
- 【bzoj1195】[HNOI2006]最短母串 AC自动机+状态压缩+BFS最短路
原文地址:http://www.cnblogs.com/GXZlegend/p/6825226.html 题目描述 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串 ...
- 【刷题】BZOJ 1195 [HNOI2006]最短母串
Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. Input 第一行是一个正整数n(n<=12) ...
- [HNOI2006]最短母串 (AC自动机+状压)
Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. Input 第一行是一个正整数n(n<=12) ...
- bzoj 1195: [HNOI2006]最短母串【状压dp】
我有病吧--明明直接枚举是否匹配就可以非要写hash,然后果然冲突了(--我个非酋居然还敢用hash 设f[s][i]为已选串状态为s并且最后一个串是i,还有预处理出g[i][j]表示最长有长为g[i ...
随机推荐
- Element源码阅读(1)
一.目的 阅读element源码旨在了解其代码的组织架构模式, 代码编写的方式, 以及组件化的一些思路, 对照自己, 从而进步. 二. 源码阅读所得 1.在element源码中的mixins目录之下, ...
- Shell(一)变量
一.简介 Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序,这个应用程序提供了一个界面,用 ...
- libvirtd.service
[root@kvm-server ~]# systemctl status libvirtd.service ● libvirtd.service - Virtualization daemon Lo ...
- adb 相关问题总结
1. adb shell权限问题$ su //root权限来启动adb server$ adb kill-server && adb start-server* daemon not ...
- webstorm注册码注册
最近jetbrains公司更新软件总是特别的快,很多私人搭建的server服务也失效了,现出一个能够永久破解的方法,非常简单,只需要2步就完成. 第一步 复制下方activation code,直接粘 ...
- 中山纪念中学培训杂题(难的都不在这里面qwq)
来中山纪中半个月了,差不多就要结束了, 写一些之前考试能更正的题解吧,还有一些不是给人做的(比如IOI2018互测.. 备注:我不会的就没有放上来了,所有数学有关的基本上都死了. 所以这里的题目都是相 ...
- 循环语句第2种 WHILE ... LOOP END LOOP;
--------第2种-------- WHILE ... LOOP END LOOP; declare n number(3) :=1; begin WHILE n&l ...
- C#-委托 lambda 匿名方法 匿名类型
1.lambda 匿名方法 匿名类型 delegate void d1(); d1 d = delegate(){Console.WriteLine("this is a test" ...
- java用freemarker实现导出excel
前几天做了jxl导出excel,现在用freemarker做一下 freemarker导出excel和导出word步骤和是实现方法是相同的. 1.制作excel模板 2.将后缀名改为ftl,放到对应的 ...
- yii自己定义CLinkPager分页
在components中自己定义LinkPager.并继承CLinkPager 代码例如以下: <? php /** * CLinkPager class file. * * @author l ...