bzoj 1195: [HNOI2006]最短母串 (状压dp)
来源:互联网 发布:python算法精解 pdf 编辑:程序博客网 时间:2024/05/21 17:05
1195: [HNOI2006]最短母串
Time Limit: 10 Sec Memory Limit: 32 MBSubmit: 1212 Solved: 405
[Submit][Status][Discuss]
Description
给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串。
Input
第一行是一个正整数n(n<=12),表示给定的字符串的个数。以下的n行,每行有一个全由大写字母组成的字符串。每个字符串的长度不超过50.
Output
只有一行,为找到的最短的字符串T。在保证最短的前提下,如果有多个字符串都满足要求,那么必须输出按字典序排列的第一个。
Sample Input
2
ABCD
BCDABC
ABCD
BCDABC
Sample Output
ABCDABC
HINT
Source
题解:状压dp
将答案中是否包含字符串i,状压起来。
f[i][j]表示到状态i,最前面的字符串为j 的最小连接方式的下一个串的编号
g[i][j] 表示状态i,最前面的字符串为j此时的长度
h[i][j]记录从哪个状态推来的。
转移的时候需要根据记录的后继还原出字符串进行对比
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<queue>#define N 15#define pa pair<int,int>using namespace std;int f[(1<<12)][13],g[(1<<12)][13],h[(1<<12)][13],can[(1<<12)][13];int n,m,ans,c[N][N];char a[N][100],b[N][100],str[2000],s[603],s1[603];int len[N],len1[N],mark[N];int calc(char a[],char b[],int len,int len1){int ans=0;for (int i=1;i<=len;i++) { int j=1; int k=i; while (a[k]==b[j]&&k<=len&&j<=len1) k++,j++; if (k==len+1) ans=max(ans,j-1); }return ans;}bool pd(char x[],char y[],int len){for (int i=1;i<=len;i++) if (x[i]<y[i]) return false; else if (x[i]>y[i]) return true;return false;}int change(int x,int sta,int lenk,int last,char s[]){int t;if (last==-1) t=calc(s,a[x],lenk,len[x]);else t=c[last][x];for (int i=t+1;i<=len[x];i++) s[++lenk]=a[x][i];if (f[sta][x]==0) return lenk;change(f[sta][x],h[sta][x],lenk,x,s);}int main(){scanf("%d",&n);for (int i=1;i<=n;i++){scanf("%s",b[i]+1);len1[i]=strlen(b[i]+1);}for (int i=1;i<=n;i++) if (!mark[i]) for (int j=1;j<=len1[i];j++) { for (int k=1;k<=n;k++) if (k!=i) { bool f=true; for (int l=1;l<=len1[k];l++) if (b[i][j+l-1]!=b[k][l]){ f=false; break; } if (f&&j+len1[k]-1<=len1[i]) mark[k]=1; } }int cnt=0;for (int i=1;i<=n;i++) if (!mark[i]) { cnt++; len[cnt]=len1[i]; for (int j=1;j<=len[cnt];j++) a[cnt][j]=b[i][j]; }n=cnt; for (int i=1;i<=n;i++) c[0][i]=0;for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (i!=j) c[i][j]=calc(a[i],a[j],len[i],len[j]);memset(f,-1,sizeof(f));queue<pa> p;for (int i=1;i<=n;i++) f[1<<(i-1)][i]=0,g[1<<(i-1)][i]=len[i],can[1<<(i-1)][i]=1, p.push(make_pair(1<<(i-1),i)); while (!p.empty()) { pa x=p.front(); p.pop(); int i=x.second; int sta=x.first; can[sta][i]=0; for (int j=1;j<=n;j++) if (!((sta>>(j-1))&1)) { for (int k=1;k<=len[j];k++) s1[k]=a[j][k]; int t=change(i,sta,len[j],-1,s1); if (f[sta|(1<<(j-1))][j]==-1) { f[sta|(1<<(j-1))][j]=i; h[sta|(1<<(j-1))][j]=sta; g[sta|(1<<(j-1))][j]=t; if (!can[sta|(1<<(j-1))][j]) p.push(make_pair(sta|(1<<(j-1)),j)); continue; } int l=change(j,sta|(1<<(j-1)),0,0,s); if (t<l) { f[sta|(1<<(j-1))][j]=i; h[sta|(1<<(j-1))][j]=sta; g[sta|(1<<(j-1))][j]=t; if (!can[sta|(1<<(j-1))][j]) p.push(make_pair(sta|(1<<(j-1)),j)); } else if (t==l) if (pd(s,s1,l)) { f[sta|(1<<(j-1))][j]=i,h[sta|(1<<(j-1))][j]=sta;if (!can[sta|(1<<(j-1))][j]) p.push(make_pair(sta|(1<<(j-1)),j)); } } }int t=(1<<n)-1; ans=2000;for (int i=1;i<=n;i++) if (f[t][i]!=-1) ans=min(ans,g[t][i]);for (int i=1;i<=600;i++) str[i]='Z';for (int i=1;i<=n;i++) if (g[t][i]==ans) { int l=change(i,t,0,0,s); if (pd(str,s,ans)) for (int j=1;j<=ans;j++) str[j]=s[j]; }for (int i=1;i<=ans;i++) printf("%c",str[i]);}
0 0
- bzoj 1195: [HNOI2006]最短母串 (状压dp)
- BZOJ 1195 [HNOI2006]最短母串 状压DP
- bzoj 1195: [HNOI2006]最短母串 状压dp
- BZOJ 1195: [HNOI2006]最短母串
- BZOJ 1195 [HNOI2006] 最短母串
- bzoj 1195 [HNOI2006]最短母串
- [BZOJ1195] [HNOI2006]最短母串(状压dp)
- [BZOJ1195][HNOI2006]最短母串(状压DP)
- 【33.28%】【BZOJ 1195】[HNOI2006]最短母串
- 大视野1195: [HNOI2006]最短母串
- BZOJ 1196: [HNOI2006]公路修建问题(二分+生成树)
- bzoj 1191 [HNOI2006]超级英雄Hero(最大基数匹配)
- bzoj 1191: [HNOI2006]超级英雄Hero (匈牙利算法)
- [BZOJ 1191][HNOI2006]超级英雄Hero(二分图匹配)
- bzoj 1192: [HNOI2006]鬼谷子的钱袋 (数论)
- bzoj 1196: [HNOI2006]公路修建问题 (最小生成树)
- BZOJ 1192 [HNOI2006]鬼谷子的钱袋(玄学)
- BZOJ 1191 [HNOI2006]超级英雄Hero(二分图匹配)
- iOS开发封装篇-利用绘图封装一个可以涂鸦的view
- React(4. 2)--数据流(实践篇)
- centos6.5修改时区
- js无缝滚动
- 【NOIP2016提高A组模拟9.24】就是乘法
- bzoj 1195: [HNOI2006]最短母串 (状压dp)
- 我的Gnome Shell桌面折腾日志
- 图像去雾--- 何凯明博士-论文笔记
- Android 启动引导页(动态生成底部导航圆点)【转】
- 12本最具影响力的程序员书籍
- 套接字编程
- 【Python开发】Python中的class继承
- 装饰模式
- Mongo分片集群搭建