大视野1195: [HNOI2006]最短母串

题目

Description


给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串。

Input

第一行是一个正整数n(n<=12),表示给定的字符串的个数。以下的n行,每行有一个全由大写字母组成的字符串。每个字符串的长度不超过50.

Output

只有一行,为找到的最短的字符串T。在保证最短的前提下,如果有多个字符串都满足要求,那么必须输出按字典序排列的第一个。

题意

题意非常简单,就是题目第一行。

解法

(S1,S2,„,Sn)之间是通过共用字符的方式来减少最后S的长度,那么遍历(S1,S2,„,Sn)的所有全排列就能找到那个最短的,这让人想到哈密顿路径(不是回路,起始点不同),用动态规划可以有O(n^2*2^n)的复杂度比O(n!)好一点。具体的是,建图mp[i][j]表示当第i个串在第j个串前面时他们能共用的最大字符个数。然后dp[i][j]表示当前位置在i,已经经过点集j(j是用二进制压缩了的状态量)的最大路的长度,因为题目还要求字典序最小的,所以我的dp[i][j]的结果是一个结构体,把路径和长度都保存了。

代码

#include
#include
struct node
{
    int val,path[15],cnt;
}dp[15][5000];//val表示路径的长度,cnt表示路径上节点的数量,path记录了具体的节点
char str[15][55],str1[700],str2[700],ans[700];//str是原始的数据,str1和str2是用path求构成的字符串时用的,ans是最后答案
int mp[15][15],len[15];//len[i]是输入的第i个字符串的长度
int cal(int k1,int k2)//算mp[k1][k2]的值
{
    int i,j,ans=0;
    for(i=0;i<=len[k1]&&i<=len[k2];i++)
    {
        for(j=0;j>k)&1))
                        continue;
                    int tmp=(j|(1<res.val||(dp[i][lim].val==res.val&&check(pp,lim,i,lim,0)))
        {
            res=dp[i][lim];
            pp=i;
        }
    }
    int tmp=res.path[0],lenth=0;
    while(str[tmp][lenth]!=0)
    {
        ans[lenth]=str[tmp][lenth];
        lenth++;
    }
    for(i=1;i


你可能感兴趣的:(大视野)