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 ...
随机推荐
- Lua开发环境搭建(Mac)
1.下载最新版的Lua,点击下载 2.下载完成后,解压压缩包,打开终端,cd进入Lua解压目录下 3. 在终端输入“make macosx”,编译lua 4.编译完成后,在终端输入”make test ...
- 【转】Hibernate映射机制之XXX.hbm.xml
http://blog.csdn.net/a9529lty/article/details/6454924[注意多对一中“多”和“一”各自的java文件.xml文件的书写格式] 另外两篇总结:http ...
- iOS开发简单高效的数据存储
在iOS开发过程中,不管是做什么应用,都会碰到数据保存的问题,你是用什么方法来持久保存数据的?这是在几乎每一次关于iOS技术的交流或讨论都会被提到的问题,而且大家对这个问题的热情持续高涨.本文主要从概 ...
- android开发之ExpandableListView的使用,实现类似QQ好友列表
由于工作需要,今天简单研究了一下ExpandableListView,做了一个类似QQ列表的Demo,和大家分享一下. 效果图如下: 先来看看主布局文件: <RelativeLayout xml ...
- 线程间操作无效 progressBar2线程不能被访问
出现这个问题解决的方法有两种第一种就是使用 // Form1.CheckForIllegalCrossThreadCalls = false;//不对跨线程的调用 使用这个的时候是判断线程是否运行正常 ...
- udp开发-dtd验证,dom解析
//博主太懒了,并没有提供范例程序 6.基于UDP开发 (1)发送方:socket->准备数据包 DatagramSocket docket = new DatagramSocket(); // ...
- Extjs combobox设置默认值
转载:http://www.54mask.com/extjs-combobox-default-value.html 相信很多人都遇到了在ExtJS框架中设置combo组件默认值的需求,ExtJS框架 ...
- jquery杂记之checkbox控制select置灰
jquery: $(function(){ $("#avg_day_live").bind("click",function(){ //点击 if($(&q ...
- OC加强-day03
#program mark - 0_18 分类的使用注意 [掌握] 1.分类的作用 作用:讲一个类分为多个模块,将相似功能的方法写在同一个模块中,方便我们后面代码的维护 "强调 1.分类中只 ...
- C#冒泡排序法程序代码
using System;using System.Collections.Generic;using System.Linq;using System.Text; namespace Console ...