UVA10723 电子人的基因

UVA10723 电子人的基因

题目比较难找附上链接:https://vjudge.net/problem/UVA-10723

题目描述:

给你两个字符串,你需要找出一个最短的字符串,使得两个给定字符串都是找出字符串的子序列

同时,还要找出这个最短的字符串的组成方案有几种。

多组数据,输出格式见样例。

 

样例输入:

3

ABAAXGF

AABXFGA

ABA

BXA

AABBA

BBABAA

 

样例输出:

Case #1: 10 9

Case #2: 4 1

Case #3: 8 10

 

题目分析:

首先不考虑寻找的串最短,只考虑使两个串均为找到的串的自序

那么很显然,我们可以直接将两个给定的字符串拼接起来,得到答案

到了这里,我们可以考虑,在这个拼接的串中,删去一些不必要的字符,来得到最优解

考虑可以删去的字符,一定同时两个串中,位置任意,所以,只要删去两个串的最长公共子序列即可

最优解的字符串长度 = len1 + len2 - len_(lcs(a,b))

考虑维护f[i][j](LCS)的同时维护g[j][j](a串匹配到i位,b串到第j位,最优解的方案数)

转移的时候,f从哪里转移,g必然也从什么地方转移(详见代码)

 

注:原题面数据丧心病狂卡了读入,两个字符串中存在空格这种东西,不能用scanf,用gets即可

 

CODE:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 
 6 #define RI register int
 7 using namespace std;
 8 typedef long long ll;
 9 
10 const int INF = 1e9 + 7;
11 const int MAXN = 50 + 5;
12 
13 #define max(a,b) ((a) > (b) ? (a) : (b))
14 #define min(a,b) ((a) < (b) ? (a) : (b))
15 
16 inline void read(int &x)
17 {
18     x = 0;
19     bool flag = 0;
20     char ch = getchar();
21     while(ch < '0' || ch > '9')
22     {
23         if(ch == '-')    flag = 1;
24         ch = getchar();
25     }
26     while(ch >= '0' && ch <= '9')
27     {
28         x = x * 10 + ch - '0';
29         ch = getchar();
30     }
31     if(flag)    x *= -1;
32 }
33 
34 int T,len1,len2,t;
35 char a[MAXN],b[MAXN];
36 ll f[MAXN][MAXN],g[MAXN][MAXN];
37 
38 void init()
39 {
40     memset(f,0,sizeof(f));
41     memset(g,0,sizeof(g));
42     memset(a,0,sizeof(a));
43     memset(b,0,sizeof(b));
44     //scanf("%s",a + 1);
45     //scanf("%s",b + 1);
46     gets(a + 1);
47     gets(b + 1);
48     len1 = strlen(a + 1);
49     len2 = strlen(b + 1);
50 }
51 
52 int main()
53 {
54     read(T);
55     while(T --)
56     {
57         init();
58         for(int i = 0;i <= max(len1,len2);i ++)
59             g[i][0] = g[0][i] = 1;
60         for(RI i = 1;i <= len1;i ++)
61         {
62             for(RI j = 1;j <= len2;j ++)
63             {
64                 if(a[i] == b[j])
65                 {
66                     f[i][j] = f[i - 1][j - 1] + 1;
67                     g[i][j] += g[i - 1][j - 1];
68                 }
69                 else
70                 {
71                     f[i][j] = max(f[i - 1][j],f[i][j - 1]);
72                     if(f[i - 1][j] > f[i][j - 1])
73                         g[i][j] += g[i - 1][j];
74                     else if(f[i - 1][j] < f[i][j - 1])
75                         g[i][j] += g[i][j - 1];
76                     else
77                         g[i][j] += g[i - 1][j] + g[i][j - 1];
78                 }
79             }
80         }
81         printf("Case #%d: %lld %lld\n",++ t,len1 + len2 - f[len1][len2],g[len1][len2]);
82     }
83     
84     return 0;
85 }
View Code

 

posted @ 2017-10-22 20:00 illyaillyasviel 阅读(...) 评论(...) 编辑 收藏