bzoj 1195
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的更多相关文章
- bzoj 1195: [HNOI2006]最短母串 爆搜
1195: [HNOI2006]最短母串 Time Limit: 10 Sec Memory Limit: 32 MBSubmit: 894 Solved: 288[Submit][Status] ...
- BZOJ 1195: [HNOI2006]最短母串
1195: [HNOI2006]最短母串 Time Limit: 10 Sec Memory Limit: 32 MBSubmit: 1346 Solved: 450[Submit][Status ...
- [BZOJ 1195] 最短母串
Link:https://www.lydsy.com/JudgeOnline/problem.php?id=1195 Solution: 看到数据范围n<=12,就要往状压DP上想 为了保证后项 ...
- 【刷题】BZOJ 1195 [HNOI2006]最短母串
Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. Input 第一行是一个正整数n(n<=12) ...
- HNOI 2006 BZOJ 1195 最短母串
题面 问题描述 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. 输入 第一行是一个正整数n(n<=12),表示给定的字 ...
- bzoj 1195: [HNOI2006]最短母串【状压dp】
我有病吧--明明直接枚举是否匹配就可以非要写hash,然后果然冲突了(--我个非酋居然还敢用hash 设f[s][i]为已选串状态为s并且最后一个串是i,还有预处理出g[i][j]表示最长有长为g[i ...
- BZOJ 1195 [HNOI2006]最短母串 (Trie图+状压+bfs最短路)
BZOJ1195 LOJ10061 题目大意:给你$n$个模式串,求一个最短且字典序最小的文本串并输出这个串,$n<=12,len<=50$ 首先对所有模式串构造$Trie$图,$Trie ...
- BZOJ 1195: [HNOI2006]最短母串 AC自动机+状压+搜索
思路比较直接. 由于 $n$ 很小,直接定义 $f[i][j]$ 表示当前在自动机中的节点 $i,$ 被覆盖串的集合为 $j$ 的方案数. #include <bits/stdc++.h> ...
- 【33.28%】【BZOJ 1195】[HNOI2006]最短母串
Time Limit: 10 Sec Memory Limit: 32 MB Submit: 1208 Solved: 402 [Submit][Status][Discuss] Descript ...
随机推荐
- cocos 的CCScheduler模块
scheduleSelector函数->查找m_pHashForTimers是否有存储回调的Obj类实例,否,创建新条目tHashTimerEntry,指向回调类实例,tHashTimerEnt ...
- Spring的StringUtils工具类
本文是转载文章,感觉比较好,如有侵权,请联系本人,我将及时删除. 原文网址:<Spring的StringUtils工具类> org.springframework.util.StringU ...
- js的意义,引用方法及变量
一 JavaScript的意义. Javascript是浏览器端的脚本语言,它能够访问web页面的元素和运行它得浏览器,从而可以操作元素,创建新的元素等.它主要的作用有: 1.以指定尺寸.位置和样式( ...
- StoryBoard页面联线跳转已经页面之间传参数
1.选中上图黄色.按住Control 把线拖到要要跳转的页面,寻找show. 2.选中联线.在右边Identifier:随便填入一个标示 3.在按钮点击事件加上如下代码 - (IBAction)but ...
- Mac Dock 效果及原理(勾股定理)
这个是苹果机上的 Dock 效果,Windows 上也有一款专门的模拟软件——RocketDock. 代码如下: <!doctype html> <html> <head ...
- EditText设置可以编辑和不可编辑状态
1.首先想到在xml中设置android:editable="false",但是如果想在代码中动态设置可编辑状态,没有找到对应的函数 2.然后尝试使用editText.setFoc ...
- Log4Qt 使用(一)
一.下载 http://sourceforge.net/projects/log4qt/develop 二.Log4Qt介绍 Log4Qt 是Apache Log4J 的Qt移植版,所以看Log4J的 ...
- LDAP索引及缓存优化
一.设置索引 索引将查找信息和 Directory Server 条目关联起来. Directory Server支持以下几种索引: 1出现索引 (pres) - 列出了具有特定属性的条目,与属性的值 ...
- Set Windows IP by Batch
netsh interface ip set address name="Local" static 192.168.1.55 255.255.255.0 192.168.1.1 ...
- Head First HTML与CSS — 布局与定位
1.流(flow)是浏览器在页面上摆放HTML元素所用的方法. 对于块元素,浏览器从上到下沿着元素流逐个显示所遇到的各个元素,会在每个块元素之间加一个换行: 对于内联元素,在水平方向会相互挨着,总体上 ...