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 ",++ t,len1 + len2 - f[len1][len2],g[len1][len2]); 82 } 83 84 return 0; 85 }