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. E - Redundant Paths - poj 3177(缩点求叶子节点)

    题意:给一个图,想让每两个点之间都有两条路相连,不过特殊的是相同的两点之间多次相连被认为是一条边,现在求最少还需要添加几条边才能做到 分析:手欠没看清楚是相同的边只能相连一次,需要去重边,缩点后求出来 ...

  2. js 等待刷新技术

  3. AvalonEdit 对于选定的文本添加前缀和后缀

    1: /// <summary> 2: /// 两边追加标志 3: /// </summary> 4: /// <param name="syntax" ...

  4. 文件上传插件Uploadify在Struts2中的应用,完整详细实例

    —>最近由于项目需要使用到一个上传插件,在网上发现uploadify挺不错,所以决定使用它,但是官网文档和例子是php的,而项目是SSI框架的,所以自己对uploadify在struts2中的使 ...

  5. c++11 : Local and Unnamed Types as Template Arguments

    In N2402, Anthony Williams proposes that local types, and unnamed types be usable as template argume ...

  6. Docker远程访问get(root)shell姿势

    0x00 概述 在用swarm来管理dockers容器集群时默认开启了2375端口,通过远程访问docker run -H tcp://ip:2375 $command 可任意执行docker命令.这 ...

  7. Accordion( 分类) 组件

    一. 加载方式 //class 加载方式<div id="box" class="easyui-accordion"style="width:3 ...

  8. SQLServer2008/2012 删除所有表视图存储过程

    SQLServer2008/2012 删除所有表视图存储过程 -------------------删除所有的表-------------------use xuwenbin111--/第1步**** ...

  9. WPF 获取屏幕分辨率(获取最大宽高)等

    double x = SystemParameters.WorkArea.Width;//得到屏幕工作区域宽度 double y = SystemParameters.WorkArea.Height; ...

  10. (转)ASP.NET版本的Kindeditor插件的使用(同步)

    昨天老大让我自己下载一个kindeditor说要放到“描述”功能中,并且不能提交(一边在textarea中写一边在label控件中将数据显示出来),由于从来没弄过,实在费了一翻劲.所以将此记录下来,一 ...