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 ...
随机推荐
- VB学习笔记
stack segment stack 'stack' dw dup() ;此处输入堆栈段代码 stack ends data segment ;IBUF OBUF 看成是内存的地址,IBUF+1和I ...
- Linux启动遇到的问题
双系统装的Ubuntu,在一次意外关机后无法进入图形界面,每次输入完密码进入桌面后又会退到密码输入界面.使用命令行df -hl查看发现根目录使用率达到100%.推测是因为意外关机导致的,但是找不到应该 ...
- android studio 导入的项目有乱码-笔记2
如果导入的项目原本就是UTF-8.且android studio编码设置为UTF-8就不会乱码.这种情况多是导入的原项目编码为GBK. 解决方法:在android studio 右下角,切换编码为GB ...
- Eclipse搭建服务器
一.首先,依次点击Window -->preferences-->Server-->Runtime environment -->add,再选择Apache,选择TOMcat的 ...
- windows8 8.1 安装完 ubuntu无法挂载 ntfs分区 解决方法
windows8 8.1 安装完 ubuntu无法挂载 ntfs分区 解决方法: 最近安装完发现8.1系统后,ubuntu无法加载以前的ntfs分区了,特别是我添加到了/etc/fstab里面了 导致 ...
- cognos 10.2.2 Framework manager使用”数据源”新建查询主题
又做了一个简单的报表,就是在Framework Manager中写个sum()的sql出个报表,可以使用使用"数据源"新建查询主题 配置查询主题后修改SQL,注意全部都是大写,要和 ...
- Hibernate的检索策略
hibernate 的中的session依照load()和get()按照参数的制定OID(ObjctID)去加载一个持久化对象.另外Query.list()方法则按照HQL语句去加载持久化的对象. 以 ...
- leetcode problem 10 Regular Expression Matching(动态规划)
Implement regular expression matching with support for '.' and '*'. '.' Matches any single character ...
- if参数小结
条件表达式 if [ -f file ] 如果文件存在 if [ -d ... ] 如果目录存在 if [ -s file ] 如果文件存在且非空 if [ -r file ...
- important的妙用
!important: 为某些样式设置具有最高权值,高于id选择器 用法: !important要写在分号的前面 例如: <p class="first">!impor ...