按照子串出现的先后考虑。令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. 成都Uber优步司机奖励政策(4月2、3日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  2. 南京Uber优步司机奖励政策(12月14日到12月20日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  3. 你的APK安全吗?来WeTest免费测!

    腾讯安全联合实验室就曾在<2018上半年互联网黑产研究报告>指出,移动端黑产规模宏大,恶意推广日均影响用户超过千万. 尤其在网络强相关的APP流行年代,当APP应用客户端上传与获取信息,大 ...

  4. VIN码识别,车架号识别,OCR扫描工具

    近年二手车交易市场火爆,对二手车估值需要了详细解二手车的历史状况,车架号(VIN码)是车辆唯一的身份标识,也是了解二手车车况的入口,车商和二手车平台会频繁的进行车况查询,VIN码扫描识别技术给车辆估值 ...

  5. Eclipse 常用快捷键 个性设置(Mac)

    推荐编程使用Mac 要是非要一个原因 那就是Apple工程师用Mac Google工程师也用Mac 1. 常用快捷键 Mac自带 Command + ←  跳到当前文本行头 Command + →  ...

  6. NGUI组件整理总结

    一图流: 注意: private void RClickUI(Vector3 newPos) { this.gameObject.SetActive(true); this.transform.loc ...

  7. 使用flask_limiter设定API配额

    前言 闲来无事,突然想到了以前做过的关于后台API安全方面的事,关于接口访问配额的设置,flask有没有很好的库支持呢?一找还真有!主要是对照了库的官方文档自己写了下dome,以供参考. # -*- ...

  8. 油田 (Oil Deposits UVA - 572)

    题目描述: 原题:https://vjudge.net/problem/UVA-572 题目思路: 1.图的DFS遍历 2.二重循环找到相邻的八个格子 AC代码: #include <iostr ...

  9. 《Effective C++》读书笔记 资源管理

    C++程序中最常用的资源包括动态分配的内存,文件描述器,互斥锁,数据库连接,网络socket等等.不论哪种资源,重要的是,当你不再使用他时,必须将他归还给系统. 一个很好的做法是以对象管理资源.把资源 ...

  10. 干货来袭:Redis5.0支持的新功能说明

    Redis5.0支持的新特性说明 本文内容来自华为云帮助中心 华为云DCS的Redis5.x版本继承了4.x版本的所有功能增强以及新的命令,同时还兼容开源Redis5.x版本的新增特性. Stream ...