Problem Statement
You are given a vector words. Return the shortest string that contains all the words as substrings. If there are several possible answers, return the one that comes first lexicographically.
题意:
给定n个大写英文构成的字符串,找到一个长度最短且字典序最小的串,使得给定的n个串都是其连续子串.
n<=12
看见n特别小首先可以考虑状压DP.
f[i][j],表示包含状况为i,最后一个位置考虑到第j个字串的最短字串.
因为给定的串也可能存在包含状况的,所以预处理一下转移
达成人生成就:在TC上做一道题
//ver_submit
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<vector>
#include<queue>
#include<map>
using namespace std;
class JoinedString
{
public:
inline string Min(string a,string b)
{
if (a.size()!=b.size()) return a.size()<b.size()?a:b;
return a<b?a:b;
}
inline void upd(string &a,string b) { a=(a=="")?b:Min(a,b); }
string joinWords(vector<string> s)
{
static string f[1<<13][13],g[13][13];
vector<string> sta;
set<string> S(s.begin(),s.end());s=vector<string> (S.begin(),S.end());
for (int i=0;i<s.size();++i)
{
string x=s[i];bool flag=1;
for (int j=0;j<s.size();++j) if (i!=j&&s[j].find(x)!=string::npos) flag=0;
if (flag) sta.push_back(x);
}
s=sta;int n=s.size();
for (int i=0;i<n;++i) for (int j=0;j<n;++j) for (int k=0;k<s[i].size()&&s[j].size();++k)
if (s[i].substr(s[i].size()-k)==s[j].substr(0,k)) g[i][j]=s[j].substr(k);
for (int i=0;i<(1<<n);++i) for (int j=0;j<n;++j) f[i][j]="";
for (int i=0;i<n;++i) f[(1<<i)][i]=s[i];
for (int i=0;i<(1<<n);++i) for (int j=0;j<n;++j)
if (i&(1<<j))
{
string x=f[i][j],t;
for (int k=0;k<n;++k) if (~(i*(1<<k))) t=x+g[j][k],upd(f[i|(1<<k)][k],t);
}
string ans="";
for (int i=0;i<n;++i) upd(ans,f[(1<<n)-1][i]);
return ans;
}
};
//ver_root
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<vector>
using namespace std;
int n;
string x,f[1<<13][13],g[13][13];//f state g transfer
vector<string> s,sta;
inline string Min(string a,string b)
{
if (a.size()!=b.size()) return a.size()<b.size()?a:b;
return a<b?a:b;
}
inline void upd(string &a,string b) { a=(a=="")?b:Min(a,b); }
int main()
{
cin>>n;
for (int i=1;i<=n;i++) cin>>x,s.push_back(x);
set<string> S(s.begin(),s.end());s=vector<string> (S.begin(),S.end());
for (int i=0;i<s.size();++i)
{
string x=s[i];bool flag=1;
for (int j=0;j<s.size();++j) if (i!=j&&s[j].find(x)!=string::npos) flag=0;
if (flag) sta.push_back(x);
}
s=sta;n=s.size();
for (int i=0;i<n;++i) for (int j=0;j<n;++j) for (int k=0;k<s[i].size()&&s[j].size();++k)
if (s[i].substr(s[i].size()-k)==s[j].substr(0,k)) g[i][j]=s[j].substr(k);
for (int i=0;i<(1<<n);++i) for (int j=0;j<n;++j) f[i][j]="";
for (int i=0;i<n;++i) f[(1<<i)][i]=s[i];
for (int i=0;i<(1<<n);++i) for (int j=0;j<n;++j)
if (i&(1<<j))
{
string x=f[i][j],t;
for (int k=0;k<n;++k) if (~(i*(1<<k))) t=x+g[j][k],upd(f[i|(1<<k)][k],t);
}
string ans="";
for (int i=0;i<n;++i) upd(ans,f[(1<<n)-1][i]);
cout<<ans<<endl;
}