• 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

    2
    ABCD
    BCDABC

    Sample Output

    ABCDABC
     
     
      本来高高兴兴写了个DP,然而发现根本无法解决字典序问题,怎么办能?
      搜吧。。。。。
      我们假设已经正确地写出了DP,从而得出了答案的长度以及一个字典序不怎么优的解,我们还是dfs枚举顺序,保证当前枚举字符串的字典序小于答案。
      一个强剪枝:如果当前所有没有选的串的“最少选择增加量”之和加上当前字符串长度大于答案直接break
      然后就过了。。。。
      maya,以后这类DP题我都会做了!
     
    #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[20][55];
    string res;
    int bstans=INF;
    namespace task1
    {
            string str[MAXN];
            char ss[MAXN][MAXS];
            int len[MAXN];
            int dis[MAXN][MAXN];
            int dp[MAXN][1<<13];
            int rec[MAXN][1<<13][2];
            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=1;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=0;i<n;i++)
                    {
                            str[i]=::str[i];
                    }
                    for (j=0;j<n;j++)
                            for (i=0;i<n;i++)
                                    if (i!=j && str[i].find(str[j])!=-1)
                                    {
                                            swap(str[n-1],str[j]);
                                            str[--n]="";
                                            j--;
                                            break;
                                    }
                    sort(str,&str[n],cmp_str);
                    for (i=0;i<n;i++)
                            len[i]=str[i].length(),strcpy(ss[i],str[i].c_str());
                    //    memset(dis,INF,sizeof(dis));
                    for (i=0;i<n;i++)
                    {
                            for (j=0;j<n;j++)
                            {
                                    if (i==j)continue;
                                    dis[i][j]=len[j];
                                    for (k1=0;k1<len[i];k1++)
                                    {
                                            bool flag=true;
                                            for (k2=0;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(0,-(len[i]-k1)+len[j]);
                                                    break;
                                            }
                                    }
                            }
                    }
                    memset(dp,INF,sizeof(dp));
                    for (i=0;i<n;i++)
                            dp[i][1<<i]=len[i];
                    int ii;
                    for (ii=0;ii<n;ii++)
                    {
                            for (k=0;k<n;k++)
                            {
                                    for (j=0;j<(1<<n);j++)
                                    {
                                            if (__builtin_popcount(j)!=ii)continue;
                                            for (i=0;i<n;i++)
                                            {
                                                    if (dp[i][j]==INF)continue;
                                                    if ((j&(1<<k))==0)
                                                    {
                                                            if (dp[k][j|(1<<k)]>dp[i][j]+dis[i][k])
                                                            {
                                                                    dp[k][j|(1<<k)]=dp[i][j]+dis[i][k];
                                                                    rec[k][j|(1<<k)][0]=i;
                                                                    rec[k][j|(1<<k)][1]=j;
                                                            }
                                                    }
                                            }
                                    }
                            }
                    }
                    int ans=INF;
                    for (i=0;i<n;i++)
                            if (ans>dp[i][(1<<n)-1])
                            {
                                    ans=dp[i][(1<<n)-1];
                                    x=i;
                                    y=(1<<n)-1;
                            }
                    vector<int> vec;
                    int xx,yy;
                    for (i=0;i<n;i++)
                    {
                            vec.push_back(x);
                            xx=x;yy=y;
                            x=rec[xx][yy][0];
                            y=rec[xx][yy][1];
                    }
                    for (int i=0;i<vec.size()/2;i++)
                            swap(vec[i],vec[vec.size()-1-i]);
                    strcat(res,ss[vec[0]]);
                    for (i=1;i<vec.size();i++)
                    {
                            strcat(res,ss[vec[i]]+len[vec[i]]-dis[vec[i-1]][vec[i]]);
                    }
                    ::res=res;
                    ::bstans=ans;
            }
    }
    int cst[20][20];
    int len[20];
    bool bad[20];
    string curs;
    int cnt;
    int n;
    bool cmp_pair(pair<char*,int> p1,pair<char*,int> p2)
    {
            return strcmp(p1.first,p2.first)<0;
    }
    int mncst[22];
    int dfs(int now,int status,int tdis,int cnt)
    {
            if (tdis>bstans)return 0;
            if (curs>res)return 0;
            int t=0,ret=1;
            for (int i=0;i<n;i++)
            {
                    if (!(status&(1<<i)))
                    {
                            t+=mncst[i];
                    }
            }
            if (t+tdis>bstans)
                    return 0;
            if (status==(1<<n)-1)
            {
                    if (bstans>tdis)
                    {
                            assert(false);
                            res=curs;
                            bstans=tdis;
                    }else
                    {
                            res=min(res,string(curs));
                    }
                    return 1;
            }
            pair<char *,int> seq[13];
            int tots=0;
            for (int i=0;i<n;i++)
                    if (!(status&(1<<i)))
                            seq[tots++]=make_pair(str[i] + len[i]-cst[now][i],i);
            sort(seq,seq+tots,cmp_pair);
            for (int i=0;i<tots;i++)
            {
                    curs+=str[seq[i].second]+(len[seq[i].second]-cst[now][seq[i].second]);
                    t=dfs(seq[i].second,status|(1<<seq[i].second),tdis+cst[now][seq[i].second],cnt*2/tots);
                    cnt-=t;
                    ret+=t;
                    curs=curs.substr(0,tdis);
                    //if (cnt<=0)break;
            }
            return ret;
    }
    
    int main()
    {
        //    freopen("input.txt","r",stdin);
            int x,y,z;
            scanf("%d",&n);
            for (int i=0;i<n;i++)
            {
                    scanf("%s",str[i]);
                    len[i]=strlen(str[i]);
            }
            task1::main(n);
            for (int i=0;i<n;i++)
            {
                    if (bad[i])continue;
                    for (int j=0;j<n;j++)
                    {
                            if (i==j)continue;
                            for (int k=0;k<len[i];k++)
                            {
                                    bool flag2=false;
                                    for (int k2=0;k+k2<len[i];k2++)
                                    {
                                            if (str[i][k2+k]!=str[j][k2])
                                            {
                                                    break;
                                            }
                                            if (k2==len[j]-1)
                                            {
                                                    flag2=true;
                                                    break;
                                            }
                                    }
                                    if (flag2)
                                            bad[j]=true;
                            }
                    }
            }
            x=0;
            for (int i=0;i<n;i++)
            {
                    if (!bad[i])
                            strcpy(str[x++],str[i]);
            }
            n=x;
            char tmp[55];
            for (int i=0;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=0;i<n;i++)
                    len[i]=strlen(str[i]);
            for (int i=0;i<n;i++)
            {
                    for (int j=0;j<n;j++)
                    {
                            if (i==j)continue;
                            for (int k=0;k<=len[i];k++)
                            {
                                    bool flag=true;
                                    for (int k2=0;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=0;i<n;i++)
            {
                    int x=INF;
                    for (int j=0;j<n;j++)
                    {
                            if (i==j)continue;
                            x=min(x,cst[j][i]);
                    }
                    mncst[i]=x;
            }
            for (int i=0;i<n;i++)
            {
                    curs=str[i];
                    dfs(i,1<<i,len[i],100000000);
            }
            cout<<res<<endl;
    }
  • 相关阅读:
    html 上传图片前预览
    php获取当月天数及当月第一天及最后一天、上月第一天及最后一天实现方法
    php 计算 pdf文件页数
    php 获取半年内每个月的订单数量, 总价, 月份
    php 获取两个数组之间不同的值
    小程序支付功能
    关于nginx的Job for nginx.service failed because the control process exited with error code.错误
    linux 安装 Apollo
    MongoDB待续。。。
    ABP vNext...待续
  • 原文地址:https://www.cnblogs.com/mhy12345/p/4513278.html
Copyright © 2020-2023  润新知