http://www.lydsy.com/JudgeOnline/problem.php?id=1195

状压DP。

首先去掉被包含的字符串。

对于字符串i和j,我们求出 当字符串j的左端点在字符串i的左端点的左边或与字符串i的左端点重合时,字符串i和字符串j可以重合的最长长度cost是多少。

就是求下面红色部分的最长长度cost:

这个强行枚举就可以了,反正数据这么小。

注意,因为我们已经去掉了被包含的字符串,所以不会出现下面这种情况:

所以去掉了被包含的字符串是为了保证当左端点单调时,右端点也是单调的

建一个图,我们在图中i连到j一条费用为cost的有向边。

然后就是求不重复经过点,可以走的最长路径。

这是哈密顿路径问题,为NP问题,但是这道题数据范围很小,可以用状压DP。

对于输出字典序最小字符串那里,我们在找决策的时候比较一下即可。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define fill(a,l,r,v) fill(a+l,a+r+1,v)
#define re(i,a,b) for(i=(a);i<=(b);i++)
#define red(i,a,b) for(i=(a);i>=(b);i--)
#define ire(i,x) for(typedef(x.begin()) i=x.begin();i!=x.end();i++)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxN=;
const int maxlen=; int N;
char s[maxN+][maxlen+]; int tempN;
char temps[maxN+][maxlen+];
int f[maxN+]; inline int smaller(char *s1,char *s2,int l1,int l2)
{
int i,len1=strlen(s1+),len2=strlen(s2+);
re(i,,min(len1-l1+,len2-l2+))if(s1[l1+i-]!=s2[l2+i-])return s1[l1+i-]<s2[l2+i-];
return len1-l1+<len2-l2+;
} inline int same(char *s1,char *s2,int l1,int l2,int len)
{
int i;
if(l1+len->strlen(s1+))return ;
if(l2+len->strlen(s2+))return ;
re(i,,len)if(s1[l1+i-]!=s2[l2+i-])return ;
return ;
} inline int check(char *s1,char *s2)
{
int i,l1=strlen(s1+),l2=strlen(s2+);
re(i,,l2-l1+)if(same(s1,s2,,i,l1))return ;
return ;
} int now,first[maxN+];
struct Tedge{int v,cost,next;}edge[maxN*maxN+];
inline void addedge(int u,int v,int cost){now++;edge[now].v=v;edge[now].cost=cost;edge[now].next=first[u];first[u]=now;} #define two(k) (1<<((k)-1))
#define wei(v,k) ((v>>(k-1))&1) int F[maxN+][(<<maxN)+],vis[maxN+][(<<maxN)+];
int head,tail;PII que[maxN*(<<maxN)+]; int cnt;char out[maxN*maxlen+]; int main()
{
/*freopen("substr.in","r",stdin);
freopen("substr.out","w",stdout);*/
int i,j;
N=gint();
re(i,,N)SF("%s\n",s[i]+);
re(i,,N)re(j,,N)if(i!=j)if(check(s[i],s[j])){f[i]=;break;}
mmcy(temps,s);
tempN=N;N=;
re(i,,tempN)if(!f[i])mmcy(s[++N],temps[i]);
if(N==)N=; now=-;mmst(first,-);
re(i,,N)re(j,,N)if(i!=j)
{
int leni=strlen(s[i]+),lenj=strlen(s[j]+),res=lenj;
while(res!= && !same(s[i],s[j],,lenj-res+,res))res--;
addedge(i,j,res);
} mmst(F,-);mmst(vis,);
head=;tail=-;
re(i,,N)F[i][two(i)]=,vis[i][two(i)]=,que[++tail]=PII(i,two(i));
while(head<=tail)
{
int u=que[head%(maxN*(<<maxN)+)].fi,state=que[head%(maxN*(<<maxN)+)].se,v,cost;head++;
vis[u][state]=;
for(i=first[u],v=edge[i].v,cost=edge[i].cost;i!=-;i=edge[i].next,v=edge[i].v,cost=edge[i].cost)
if(!wei(state,v) && F[u][state]+cost>F[v][state+two(v)])
{
F[v][state+two(v)]=F[u][state]+cost;
if(!vis[v][state+two(v)])
{
vis[v][state+two(v)]=;
que[(++tail)%(maxN*(<<maxN)+)]=PII(v,state+two(v));
}
}
} now=-;mmst(first,-);
re(i,,N)re(j,,N)if(i!=j)
{
int leni=strlen(s[i]+),lenj=strlen(s[j]+),res=lenj;
while(res!= && !same(s[i],s[j],,lenj-res+,res))res--;
addedge(j,i,res);
} int u=-,state=two(N+)-;
re(i,,N)if(u==- || F[u][state]<F[i][state] || (F[u][state]==F[i][state] && smaller(s[i],s[u],,)))u=i;
re(i,,strlen(s[u]+))out[++cnt]=s[u][i];
for(int T=N-;T;T--)
{
int p=-,o,v,cost;
for(i=first[u],v=edge[i].v,cost=edge[i].cost;i!=-;i=edge[i].next,v=edge[i].v,cost=edge[i].cost)
if(wei(state,v) && F[v][state-two(u)]+cost==F[u][state])
if(p==- || smaller(s[v],s[p],cost+,o))
p=v,o=cost+;
re(i,o,strlen(s[p]+))out[++cnt]=s[p][i];
state-=two(u);
u=p;
}
re(i,,cnt)putchar(out[i]);putchar('\n');
return ;
}

bzoj 1195的更多相关文章

  1. bzoj 1195: [HNOI2006]最短母串 爆搜

    1195: [HNOI2006]最短母串 Time Limit: 10 Sec  Memory Limit: 32 MBSubmit: 894  Solved: 288[Submit][Status] ...

  2. BZOJ 1195: [HNOI2006]最短母串

    1195: [HNOI2006]最短母串 Time Limit: 10 Sec  Memory Limit: 32 MBSubmit: 1346  Solved: 450[Submit][Status ...

  3. [BZOJ 1195] 最短母串

    Link:https://www.lydsy.com/JudgeOnline/problem.php?id=1195 Solution: 看到数据范围n<=12,就要往状压DP上想 为了保证后项 ...

  4. 【刷题】BZOJ 1195 [HNOI2006]最短母串

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

  5. HNOI 2006 BZOJ 1195 最短母串

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

  6. bzoj 1195: [HNOI2006]最短母串【状压dp】

    我有病吧--明明直接枚举是否匹配就可以非要写hash,然后果然冲突了(--我个非酋居然还敢用hash 设f[s][i]为已选串状态为s并且最后一个串是i,还有预处理出g[i][j]表示最长有长为g[i ...

  7. BZOJ 1195 [HNOI2006]最短母串 (Trie图+状压+bfs最短路)

    BZOJ1195 LOJ10061 题目大意:给你$n$个模式串,求一个最短且字典序最小的文本串并输出这个串,$n<=12,len<=50$ 首先对所有模式串构造$Trie$图,$Trie ...

  8. BZOJ 1195: [HNOI2006]最短母串 AC自动机+状压+搜索

    思路比较直接. 由于 $n$ 很小,直接定义 $f[i][j]$ 表示当前在自动机中的节点 $i,$ 被覆盖串的集合为 $j$ 的方案数. #include <bits/stdc++.h> ...

  9. 【33.28%】【BZOJ 1195】[HNOI2006]最短母串

    Time Limit: 10 Sec  Memory Limit: 32 MB Submit: 1208  Solved: 402 [Submit][Status][Discuss] Descript ...

随机推荐

  1. JS(四)

    JS的属性好多,方法好多,一下子塞进来真的需要时间消化,很多东西都是当时记得很清楚,但忘得很快,看来需要经常去复习,主要是感觉后面一点的练习题好像少了点,所以就显得不是很熟练. 1.About Tim ...

  2. 数组对象元素的添加,String对象,BOM对象以及文档对象的获取

    数组对象的删除有三种方法: pop();        //移除最后一个元素并返回该元素值shift();      //移除最前一个元素并返回该元素值,数组中元素自动前移splice(0,2); / ...

  3. StoryBoard页面联线跳转已经页面之间传参数

    1.选中上图黄色.按住Control 把线拖到要要跳转的页面,寻找show. 2.选中联线.在右边Identifier:随便填入一个标示 3.在按钮点击事件加上如下代码 - (IBAction)but ...

  4. C++基础学习笔记----第十三课(操作符重载-下)

    本节主要讲使用成员函数重载操作符,包括[],=,(),->四种操作符的重载以及&&和||的问题. 类的成员函数进行操作符重载 基本概念 类的成员函数也可以进行操作符的重载.类的普 ...

  5. Welcome to Apache™ Hadoop®!

    What Is Apache Hadoop? Getting Started Download Hadoop Who Uses Hadoop? News 15 October, 2013: relea ...

  6. Nginx 主配置文件参数详解

    Nginx 主配置文件参数详解 Nginx 安装完毕后,会有响应的安装目录,安装目录里 nginx.conf 为 nginx 的主配置文件, ginx 主配置文件分为 4 部分,main(全局配置). ...

  7. ASP.NET MVC上传文件的几种方法

    1.Form表单提交 <p>Form提交</p> <form action="@Url.Action("SavePictureByForm" ...

  8. Android系统中长按事件的实现机制解析

    在Android的触摸消息中,已经实现了三种监测,它们分别是 1)pre-pressed:对应的语义是用户轻触(tap)了屏幕 2)pressed:对应的语义是用户点击(press)了屏幕 3)lon ...

  9. Word 2010发布博客文章

    只测试了cnblog 1.新建文件选择word 2010自带的博客文章模板 2.在管理账户中新建一个博客账户,也就是你自己在博客园的账户,博客选其他 3.然后选择下一步,博客的URL在自己的博客设置里 ...

  10. php 练习一 5月5日

    练习题一:通过登录者找到他的好友并显示在页面上 <title>无标题文档</title> <style type="text/css"> * { ...