BZOJ1195 HNOI2006最短母串(状压dp)
按照子串出现的先后考虑。令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)的更多相关文章
- [bzoj1195][HNOI2006]最短母串_动态规划_状压dp
最短母串 bzoj-1195 HNOI-2006 题目大意:给一个包含n个字符串的字符集,求一个字典序最小的字符串使得字符集中所有的串都是该串的子串. 注释:$1\le n\le 12$,$1\le ...
- BZOJ1195 [HNOI2006]最短母串 【状压dp】
题目 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. 输入格式 第一行是一个正整数n(n<=12),表示给定的字符串的 ...
- Bzoj1195 [HNOI2006]最短母串 [状态压缩]
Time Limit: 10 Sec Memory Limit: 32 MBSubmit: 1304 Solved: 439 Description 给定n个字符串(S1,S2,„,Sn),要求找 ...
- [bzoj1195] [hnoi2006] 最短母串
本题是一个经典的状压dp问题,在紫书中有着加强版的例题. 本题的难度主要体现在:如何输出字符串字典序最小. 为了解决这个问题,我们有两种常用方案: 1) 我们可以采用bfs输出路径的方法,使用+1来输 ...
- BZOJ1195[HNOI2006]最短母串——AC自动机+BFS+状态压缩
题目描述 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. 输入 第一行是一个正整数n(n<=12),表示给定的字符串的 ...
- Bzoj1195 [HNOI2006]最短母串 [AC自动机]
Time Limit: 10 Sec Memory Limit: 32 MBSubmit: 1304 Solved: 439 Description 给定n个字符串(S1,S2,„,Sn),要求找 ...
- bzoj1195 [HNOI2006]最短母串 AC 自动机+状压+bfs
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=1195 题解 建立 AC 自动机,然后构建出 trie 图. 然后直接在 trie 图上走.但是 ...
- BZOJ1195 [HNOI2006]最短母串 AC自动机 bfs
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 传送门 - BZOJ1195 题意概括 给出一堆串,然后求一个包含这些串的所有串的最短的中的字典序最小的. 题解 先造一个AC ...
- [BZOJ1195]:[HNOI2006]最短母串(AC自动机+BFS)
题目传送门 题目描述 给定n个字符串(S1,S2,…,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,…,Sn)都是T的子串. 输入格式 第一行是一个正整数n,表示给定的字符串的个数 ...
随机推荐
- 常用排序算法的C++实现
排序是将一组"无序"的记录序列调整为"有序"的记录序列. 假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在 ...
- HDU 5972 Regular Number
Regular Number http://acm.hdu.edu.cn/showproblem.php?pid=5972 题意: 给定一个字符串,求多少子串满足,子串的第i位,只能是给定的数(小于等 ...
- javaweb(五)——Servlet开发(一)
一.Servlet简介 Servlet是sun公司提供的一门用于开发动态web资源的技术. Sun公司在其API中提供了一个servlet接口,用户若想用发一个动态web资源(即开发一个Java程序向 ...
- selenium自动化测试资源整理
1. 所有版本chrome下载 是不是很难找到老版本的chrome?博主收集了几个下载chrome老版本的网站,其中哪个下载的是原版的就不得而知了. http://www.slimjet.com/ch ...
- linux部署maven
1.下载安装包 https://maven.apache.org/download.cgi 2.解压,并配置环境变量 vim /etc/profile export MAVEN_HOME=maven目 ...
- SecureCRT 注册
http://download.csdn.net/download/xia2011214228/9952983 1.下载后解压到安装目录 2.输入自己要注册的:name company 后genera ...
- leetcode-二进制手表
二进制手表顶部有 4 个 LED 代表小时(0-11),底部的 6 个 LED 代表分钟(0-59). 每个 LED 代表一个 0 或 1,最低位在右侧. 例如,上面的二进制手表读取 “3:25”. ...
- Java基础知识:Java实现Map集合二级联动1
Java实现Map集合二级联动 Map集合可以保存键值映射关系,这非常适合本实例所需要的数据结构,所有省份信息可以保存为Map集合的键,而每个键可以保存对应的城市信息,本实例就是利用Map集合实现了省 ...
- jstat命令
jstat命令使用 jstat命令可以查看堆内存各部分的使用量,以及加载类的数量.命令的格式如下: jstat [-命令选项] [vmid] [间隔时间/毫秒] [查询次数] 注意:使用的jdk版本是 ...
- python常用命令—ipython3环境下获取某个文件夹下的文件列表
import os os.listdir('文件夹路径')