bzoj 1195: [HNOI2006]最短母串 爆搜
1195: [HNOI2006]最短母串
Time Limit: 10 Sec Memory Limit: 32 MB
Submit: 894 Solved: 288
[Submit][Status][Discuss]
Description
给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串。
Input
第一行是一个正整数n(n<=12),表示给定的字符串的个数。以下的n行,每行有一个全由大写字母组成的字符串。每个字符串的长度不超过50.
Output
只有一行,为找到的最短的字符串T。在保证最短的前提下,如果有多个字符串都满足要求,那么必须输出按字典序排列的第一个。
Sample Input
ABCD
BCDABC
Sample Output
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<vector>
#include<cassert>
using namespace std;
#define MAXN 13
#define MAXS 55
#define INF 0x3f3f3f3f
char str[][];
string res;
int bstans=INF;
namespace task1
{
string str[MAXN];
char ss[MAXN][MAXS];
int len[MAXN];
int dis[MAXN][MAXN];
int dp[MAXN][<<];
int rec[MAXN][<<][];
char res[MAXN*MAXS];
void deal(int &x,int y)
{
if (x>y)x=y;
}
bool cmp_str(const string& s1,const string &s2)
{
for (int i=;i<=min(s1.length(),s2.length());i++)
{
if (s1[s1.length()-i]!=s2[s2.length()-i])return s1[s1.length()-i]<s2[s2.length()-i];
}
return false;
}
int main(int n)
{
int m,i,j,k1,k2,k;
int x,y;
for (i=;i<n;i++)
{
str[i]=::str[i];
}
for (j=;j<n;j++)
for (i=;i<n;i++)
if (i!=j && str[i].find(str[j])!=-)
{
swap(str[n-],str[j]);
str[--n]="";
j--;
break;
}
sort(str,&str[n],cmp_str);
for (i=;i<n;i++)
len[i]=str[i].length(),strcpy(ss[i],str[i].c_str());
// memset(dis,INF,sizeof(dis));
for (i=;i<n;i++)
{
for (j=;j<n;j++)
{
if (i==j)continue;
dis[i][j]=len[j];
for (k1=;k1<len[i];k1++)
{
bool flag=true;
for (k2=;k2+k1<len[i] && k2<len[j];k2++)
{
if (ss[i][k1+k2]!=ss[j][k2])
{
flag=false;
break;
}
}
if (flag)
{
dis[i][j]=max(,-(len[i]-k1)+len[j]);
break;
}
}
}
}
memset(dp,INF,sizeof(dp));
for (i=;i<n;i++)
dp[i][<<i]=len[i];
int ii;
for (ii=;ii<n;ii++)
{
for (k=;k<n;k++)
{
for (j=;j<(<<n);j++)
{
if (__builtin_popcount(j)!=ii)continue;
for (i=;i<n;i++)
{
if (dp[i][j]==INF)continue;
if ((j&(<<k))==)
{
if (dp[k][j|(<<k)]>dp[i][j]+dis[i][k])
{
dp[k][j|(<<k)]=dp[i][j]+dis[i][k];
rec[k][j|(<<k)][]=i;
rec[k][j|(<<k)][]=j;
}
}
}
}
}
}
int ans=INF;
for (i=;i<n;i++)
if (ans>dp[i][(<<n)-])
{
ans=dp[i][(<<n)-];
x=i;
y=(<<n)-;
}
vector<int> vec;
int xx,yy;
for (i=;i<n;i++)
{
vec.push_back(x);
xx=x;yy=y;
x=rec[xx][yy][];
y=rec[xx][yy][];
}
for (int i=;i<vec.size()/;i++)
swap(vec[i],vec[vec.size()--i]);
strcat(res,ss[vec[]]);
for (i=;i<vec.size();i++)
{
strcat(res,ss[vec[i]]+len[vec[i]]-dis[vec[i-]][vec[i]]);
}
::res=res;
::bstans=ans;
}
}
int cst[][];
int len[];
bool bad[];
string curs;
int cnt;
int n;
bool cmp_pair(pair<char*,int> p1,pair<char*,int> p2)
{
return strcmp(p1.first,p2.first)<;
}
int mncst[];
int dfs(int now,int status,int tdis,int cnt)
{
if (tdis>bstans)return ;
if (curs>res)return ;
int t=,ret=;
for (int i=;i<n;i++)
{
if (!(status&(<<i)))
{
t+=mncst[i];
}
}
if (t+tdis>bstans)
return ;
if (status==(<<n)-)
{
if (bstans>tdis)
{
assert(false);
res=curs;
bstans=tdis;
}else
{
res=min(res,string(curs));
}
return ;
}
pair<char *,int> seq[];
int tots=;
for (int i=;i<n;i++)
if (!(status&(<<i)))
seq[tots++]=make_pair(str[i] + len[i]-cst[now][i],i);
sort(seq,seq+tots,cmp_pair);
for (int i=;i<tots;i++)
{
curs+=str[seq[i].second]+(len[seq[i].second]-cst[now][seq[i].second]);
t=dfs(seq[i].second,status|(<<seq[i].second),tdis+cst[now][seq[i].second],cnt*/tots);
cnt-=t;
ret+=t;
curs=curs.substr(,tdis);
//if (cnt<=0)break;
}
return ret;
} int main()
{
// freopen("input.txt","r",stdin);
int x,y,z;
scanf("%d",&n);
for (int i=;i<n;i++)
{
scanf("%s",str[i]);
len[i]=strlen(str[i]);
}
task1::main(n);
for (int i=;i<n;i++)
{
if (bad[i])continue;
for (int j=;j<n;j++)
{
if (i==j)continue;
for (int k=;k<len[i];k++)
{
bool flag2=false;
for (int k2=;k+k2<len[i];k2++)
{
if (str[i][k2+k]!=str[j][k2])
{
break;
}
if (k2==len[j]-)
{
flag2=true;
break;
}
}
if (flag2)
bad[j]=true;
}
}
}
x=;
for (int i=;i<n;i++)
{
if (!bad[i])
strcpy(str[x++],str[i]);
}
n=x;
char tmp[];
for (int i=;i<n;i++)
for (int j=i;j<n;j++)
if (string(str[i])>string(str[j]))
{
strcpy(tmp,str[i]);
strcpy(str[i],str[j]);
strcpy(str[j],tmp);
}
for (int i=;i<n;i++)
len[i]=strlen(str[i]);
for (int i=;i<n;i++)
{
for (int j=;j<n;j++)
{
if (i==j)continue;
for (int k=;k<=len[i];k++)
{
bool flag=true;
for (int k2=;k2+k<len[i];k2++)
{
if (str[i][k2+k]!=str[j][k2])
{
flag=false;
break;
}
}
if (flag)
{
cst[i][j]=len[j]-(len[i]-k);
break;
}
}
}
}
for (int i=;i<n;i++)
{
int x=INF;
for (int j=;j<n;j++)
{
if (i==j)continue;
x=min(x,cst[j][i]);
}
mncst[i]=x;
}
for (int i=;i<n;i++)
{
curs=str[i];
dfs(i,<<i,len[i],);
}
cout<<res<<endl;
}
bzoj 1195: [HNOI2006]最短母串 爆搜的更多相关文章
- BZOJ 1195: [HNOI2006]最短母串
1195: [HNOI2006]最短母串 Time Limit: 10 Sec Memory Limit: 32 MBSubmit: 1346 Solved: 450[Submit][Status ...
- bzoj 1195 [HNOI2006]最短母串 bfs 状压 最短路 AC自动机
LINK:最短母串 求母串的问题.不适合SAM. 可以先简化问题 考虑给出的n个字符串不存在包含关系. 那么 那么存在的情况 只可能有 两个字符串拼接起来能表示另外一个字符串 或者某个字符串的后缀可以 ...
- 【刷题】BZOJ 1195 [HNOI2006]最短母串
Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. Input 第一行是一个正整数n(n<=12) ...
- BZOJ 1195 [HNOI2006]最短母串 (Trie图+状压+bfs最短路)
BZOJ1195 LOJ10061 题目大意:给你$n$个模式串,求一个最短且字典序最小的文本串并输出这个串,$n<=12,len<=50$ 首先对所有模式串构造$Trie$图,$Trie ...
- bzoj 1195: [HNOI2006]最短母串【状压dp】
我有病吧--明明直接枚举是否匹配就可以非要写hash,然后果然冲突了(--我个非酋居然还敢用hash 设f[s][i]为已选串状态为s并且最后一个串是i,还有预处理出g[i][j]表示最长有长为g[i ...
- BZOJ 1195: [HNOI2006]最短母串 AC自动机+状压+搜索
思路比较直接. 由于 $n$ 很小,直接定义 $f[i][j]$ 表示当前在自动机中的节点 $i,$ 被覆盖串的集合为 $j$ 的方案数. #include <bits/stdc++.h> ...
- 【状态压缩dp】1195: [HNOI2006]最短母串
一个清晰的思路就是状压dp:不过也有AC自动机+BFS的做法 Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T ...
- 1195: [HNOI2006]最短母串 - BZOJ
Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串.Input 第一行是一个正整数n(n<=12), ...
- 1195: [HNOI2006]最短母串
思路:好像以前谁问过我这题... 状个压就好啦, 把包含在其他串中的字符串删掉, 预处理除每两个字符串之间的关系, dp[ state ][ i ] 表示在state的状态下, 最后一个字符串是第i ...
随机推荐
- JVM中的Stack和Heap
Stack: 是内存指令区.Java基本数据类型,Java指令代码,常量都保存在stack中,方法是指令也保存在stack中. 由于stack是内存是顺序分配,而且定长,不存在内存回收问题.存取速度快 ...
- 【转载】NIO服务端序列图
步骤一:打开ServerSocketChannel,用于监听客户端的连接,它是所有客户端连接的父管道,代码示例如下: ServerSocketChannel acceptorSvr = ServerS ...
- datetimepicker 初始化只显示年
$("#overdue2").datetimepicker({ format: 'yyyy', autoclose: true, startView:4, minView:4, t ...
- postgresql行转列并拼接字符串
有这样一张表: ; id | kw ----+-------- 1 | big 1 | hello 2 | oracle 2 | small 2 | apple 3 | shit( ...
- ASP.NET MVC(一) 什么是Razor
Razor 是一种向网页添加基于服务器的代码的标记语法 Razor 不是编程与语言.它是服务端标记语言. 当网页被写入浏览器时,基于服务器的代码能够创建动态内容.在网页加载时,服务器在向浏览器返回页面 ...
- 设置repeater每行多少个的方法
前台代码: <asp:ScriptManagerProxy ID="ScriptManagerProxy1" runat="server">< ...
- Android中使用shape实现EditText圆角
之前看到手机上的百度editText控件是圆角的就尝试做了一下,看了看相关的文章. 因为代码少,看看就知道了.所以下面我就直接贴上代码供大家参考,有其他的好方法记得分享哦~ 整个代码不涉及JAVA代码 ...
- js读取Excel文件数据-IE浏览器
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head ...
- php中怎么实现后台执行?
http://www.cnblogs.com/zdz8207/p/3765567.html php中实现后台执行的方法: ignore_user_abort(true); // 后台运行set_tim ...
- 【转载】Oracle层次查询和分析函数
摘要 一组连续的数,去掉中间一些数,如何求出剩下的数的区间(即号段)?知道号段的起止,如何求出该号段内所有的数?知道一个大的号段范围和已经取过的号段,如何求出可用的号段?利用Oracle提供的强大的查 ...