按照子串出现的先后考虑。令f[i][j]为已经出现的字符串集合为i,最后一个出现的字符串为j时的最短串长,预处理一下任意两个串的最长重叠长度,转移显然。有点麻烦的是字典序,强行增加代码难度。

  另一个比较简单的做法是上AC自动机,建出来后类似地令f[i][j]为已经出现的字符串集合为i,在自动机上点j时的最短串长,相当于跑一个最短路,bfs时每次优先选字典序最小的边即可。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 12
#define M 52
int n,len[N],d[N][N];
char s[N][M];
struct str
{
int n;char s[N*M];
bool operator <(const str&a) const
{
for (int i=;i<=n;i++)
if (s[i]!=a.s[i]) return s[i]<a.s[i];
return ;
}
};
str get(int p,int q);
struct data
{
int i,j,x,n,s[N+];
bool operator <(const data&a) const
{
if (x!=a.x) return x<a.x;
return get(i,j)<get(a.i,a.j);
}
}f[<<N][N];
str get(int p,int q)
{
int n=f[p][q].n;
str v;memset(v.s,,sizeof(v.s));
int x=len[f[p][q].s[]];
for (int i=;i<=len[f[p][q].s[]];i++) v.s[i]=s[f[p][q].s[]][i];
for (int i=;i<=n;i++)
for (int j=d[f[p][q].s[i-]][f[p][q].s[i]]+;j<=len[f[p][q].s[i]];j++)
v.s[++x]=s[f[p][q].s[i]][j];
v.n=x;
return v;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj1195.in","r",stdin);
freopen("bzoj1195.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read();
for (int i=;i<n;i++) scanf("%s",s[i]+),len[i]=strlen(s[i]+);
for (int i=;i<n;i++)
for (int j=;j<n;j++)
if (i!=j)
for (int k=;k<=len[i];k++)
{
bool flag=;
for (int x=;x<=len[j]&&k+x-<=len[i];x++)
if (s[i][k+x-]!=s[j][x]) {flag=;break;}
if (flag) {d[i][j]=min(len[i]-k+,len[j]);break;}
}
for (int i=;i<(<<n);i++)
for (int j=;j<n;j++)
f[i][j].x=,f[i][j].i=i,f[i][j].j=j;
for (int i=;i<n;i++) f[<<i][i].x=len[i],f[<<i][i].s[]=i,f[<<i][i].n=;
for (int i=;i<(<<n);i++)
for (int j=;j<n;j++)
if (i&(<<j))
for (int k=;k<n;k++)
if (!(i&(<<k)))
if (d[j][k]==len[k]) f[i|(<<k)][j]=min(f[i|(<<k)][j],f[i][j]),f[i|(<<k)][j].i=i|(<<k);
else
{
data t=f[i][j];
f[i][j].x+=len[k]-d[j][k];
f[i][j].s[++f[i][j].n]=k;
f[i|(<<k)][k]=min(f[i|(<<k)][k],f[i][j]),f[i|(<<k)][k].i=i|(<<k),f[i|(<<k)][k].j=k;
f[i][j]=t;
}
for (int i=;i<n;i++) f[(<<n)-][]=min(f[(<<n)-][],f[(<<n)-][i]),f[(<<n)-][].j=;
printf("%s",get((<<n)-,).s+);
return ;
}

BZOJ1195 HNOI2006最短母串(状压dp)的更多相关文章

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

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

  2. BZOJ1195 [HNOI2006]最短母串 【状压dp】

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

  3. Bzoj1195 [HNOI2006]最短母串 [状态压缩]

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

  4. [bzoj1195] [hnoi2006] 最短母串

    本题是一个经典的状压dp问题,在紫书中有着加强版的例题. 本题的难度主要体现在:如何输出字符串字典序最小. 为了解决这个问题,我们有两种常用方案: 1) 我们可以采用bfs输出路径的方法,使用+1来输 ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. mysql using filesort Using temporary

    using filesort 一般人的回答是: “当行数据太大,导致内存无法容下这些数据产生的临时表时,他们就会被放入磁盘中排序.”  很不幸,这个答案是错的 ,临时表在太大的时候确实会到磁盘离去,但 ...

  2. Selenium(Python)页面对象+数据驱动测试框架

    整个工程的目录结构: 常用方法类: class SeleniumMethod(object): # 封装Selenium常用方法 def __init__(self, driver): self.dr ...

  3. Linux命令应用大词典-第31章 设备管理

    31.1 udevadm info:查询udev数据库中的设备信息 31.2 mkdnod:创建块设备和字符设备文件 31.3 MAKEDEV:创建/dev中的设备 31.4 lsblk:列出块设备信 ...

  4. 关于java获取网页内容

    最近项目需求,做一些新闻站点的爬取工作.1.简单的jsoup爬取,静态页面形式: String url="a.atimo.cn";//静态页面链接地址Document doc = ...

  5. (原) MaterialEditor部- UmateriaEditor中 Node编译过程和使用(3)

    @author: 白袍小道 转载说明原处 插件同步在GITHUB: DaoZhang_XDZ         说明 1.本篇是接着-----(原) MaterialEditor部- UmateriaE ...

  6. python图片大小处理;

    循环一个目录将下面的所有png或者jpg文件全部缩小一定比例:     from PIL import Image import os,re work_dir = 'C:\\Users\\Admini ...

  7. LeetCode 98——验证二叉搜索树

    1. 题目 2. 解答 2.1. 方法一 我们初始化根节点的范围为长整形数据的最小最大值 \([LONG\_MIN,LONG\_MAX]\),则其左子节点的取值范围为 \([LONG\_MIN,根节点 ...

  8. C#2d命令行小游戏

    [ 星 辰 · 第 二 条 约 定 ] 要求 空地:空格 | 边界/墙:'█' | 人物:'♜' 实现人物的上下左右移动 记录关系图.流程图.设计过程遇到的问题及解决 项目压缩包 [项目源码](htt ...

  9. MFC消息处理

    1.MFC窗口如何与AfxWndProc建立联系. 当一个新的CWnd派生类创建时,在调用CWnd::CreateEx()过程中,MFC都会安装AfxCbtFilterHook().这个Hook将拦截 ...

  10. YaoLingJump开发者日志(七)

      LGame用起来真是各种蛋疼,插背景都可以显示不出来.在屏幕结束后释放资源,重载该屏幕时再setbackground也不行,直接用Lpaper当background更不行,会把tilemap上的东 ...