Time Limit: 10 Sec  Memory Limit: 32 MB
Submit: 1304  Solved: 439

Description

给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串。

Input

第一行是一个正整数n(n<=12),表示给定的字符串的个数。以下的n行,每行有一个全由大写字母组成的字符串。每个字符串的长度不超过50.

Output

只有一行,为找到的最短的字符串T。在保证最短的前提下,如果有多个字符串都满足要求,那么必须输出按字典序排列的第一个。

Sample Input

2
ABCD
BCDABC

Sample Output

ABCDABC

HINT

 

Source

AC自动机+BFS:http://www.cnblogs.com/SilverNebula/p/6445516.html

状压DP+神(bao)奇(li)预处理

先找出所有被其他串包含的串并扔掉(显然)

暴力预处理出每两个串连接起来,公共部分的长度。

进行状压DP,暴力储存每个状态对应的字符串。

在所有的11111...的最终状态中,暴力找出字典序最小的那个

是不是很神(bao)奇(li)?

不知道为何,用strcmp会TLE(也可能是别的处理不到位),各处优化了一下,手写了比较函数,终于过了

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int INF=0x3f3f3f3f;
const int mxn=;
int n;
struct bind{
char s[];
int len;
bool operator < (const bind y) const {
if(len!=y.len)return len<y.len;
for(int i=;i<len;i++)
if(s[i]!=y.s[i])return s[i]<y.s[i];
return ;
}
}f[<<][],s[];
int c[][];
bool ban[mxn]; bool ovl(int i,int j){//判断能否覆盖
if(s[i].len<s[j].len)return ;
char *p=strstr(s[i].s,s[j].s);
if(p==NULL)return ;
return ;
}
int clc(int x,int y){//统计共用串长度
bool flag=;
for(int i=max(,s[x].len-s[y].len);i<s[x].len;i++){
flag=;
for(int j=i;j<s[x].len;j++)
if(s[x].s[j]!=s[y].s[j-i]){flag=;break;}
if(flag)return s[x].len-i;//--1
}
return ;
}
bind merge(int S,int u,int v){//字符串合并
bind tmp=f[S][u];
strcat(tmp.s,s[v].s+c[u][v]);
tmp.len=f[S][u].len-c[u][v]+s[v].len;
// printf("merge:%d %d %d :%d\n",S,u,v,tmp.len);
return tmp;
}
void Dp(){
int i,j,ed=(<<n)-;
for(i=;i<=ed;i++)
for(j=;j<n;j++)f[i][j].len=INF;//init
for(i=;i<n;i++)f[<<i][i]=s[i];
for(i=;i<=ed;i++){
for(j=;j<n;j++){
if((i>>j)&)
for(int k=;k<n;k++){
if((i>>k)&)continue;
bind tmp=merge(i,j,k);
if(tmp<f[i|(<<k)][k])f[i|(<<k)][k]=tmp;
}
}
}
}
int main(){
int i,j;
scanf("%d",&n);
for(i=;i<n;i++)scanf("%s",s[i].s),s[i].len=strlen(s[i].s);
for(i=;i<n;i++)
for(j=;j<n;j++)
if(i!=j && ovl(i,j) && !ban[i])ban[j]=;
int cnt=;
for(i=;i<n;i++)if(!ban[i])s[cnt++]=s[i];
n=cnt;
for(i=;i<n;i++)
for(j=;j<n;j++)
if(i!=j)c[i][j]=clc(i,j);
Dp();
int ans=,ed=(<<n)-;
for(i=;i<n;i++)
if(f[ed][i]<f[ed][ans])ans=i;
printf("%s",f[ed][ans].s);
return ;
}

Bzoj1195 [HNOI2006]最短母串 [状态压缩]的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. BZOJ1195 HNOI2006最短母串(状压dp)

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

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

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

  8. BZOJ1195: [HNOI2006]最短母串(Trie图,搜索)

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

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

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

随机推荐

  1. 牛客小白月赛5 I 区间 (interval) 【前缀和】

    链接:https://www.nowcoder.com/acm/contest/135/I 题目描述 Apojacsleam喜欢数组. 他现在有一个n个元素的数组a,而他要对a[L]-a[R]进行M次 ...

  2. 【计数】cf223C. Partial Sums

    考试时候遇到这种题只会找规律 You've got an array a, consisting of n integers. The array elements are indexed from ...

  3. 【Ecshop】修改处理用户购物车的行为

    Ecshop v2.7.3的购物车处理方面在现在看来有比较反用户体验的设计: 用户未登录时加入购物车的商品,在用户登录后会被清空而不是加入到登录用户的购物车中: 用户登录后加入购物车的商品,在退出后会 ...

  4. PHP 二维数组某个字段进行排序

    /** * @param $arrUsers * @return mixed *二维数组某个字段进行排序 */ function quick_sort($arrUsers) { $sort = arr ...

  5. JZOJ 5773. 【NOIP2008模拟】简单数学题

    5773. [NOIP2008模拟]简单数学题 (File IO): input:math.in output:math.out Time Limits: 1000 ms  Memory Limits ...

  6. python爬取豆瓣top250的电影数据并存入excle

    爬取网址: https://movie.douban.com/top250 一:爬取思路(新手可以看一下) : 1:定义两个函数,一个get_page函数爬取数据,一个save函数保存数据,mian中 ...

  7. Xadmin后台管理系统搭建基于Django1.11.11+Python3.6

    安装python及Django百度即可 主要介绍Xadmin安装 访问地址:https://github.com/sshwsfc/xadmin  下载 安装好之后,将xamdin目录复制到项目 我放在 ...

  8. c++ 操作符优先级

    优先级 操作符 描述 例子 结合性 1 ()[]->.::++-- 调节优先级的括号操作符数组下标访问操作符通过指向对象的指针访问成员的操作符通过对象本身访问成员的操作符作用域操作符后置自增操作 ...

  9. 递推:Number Sequence(mod找规律)

    解题心得: 1.对于数据很大,很可怕,不可能用常规手段算出最后的值在进行mod的时候,可以思考找规律. 2.找规律时不必用手算(我傻,用手算了好久).直接先找前100项进行mod打一个表出来,直接看就 ...

  10. Java最小堆解决TopK问题

    TopK问题是指从大量数据(源数据)中获取最大(或最小)的K个数据. TopK问题是个很常见的问题:例如学校要从全校学生中找到成绩最高的500名学生,再例如某搜索引擎要统计每天的100条搜索次数最多的 ...