【TopCoder SRM302Div1 900】JoinedString

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值