Light oj 1013 - Love Calculator (LCS变形)
题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1013
题意:
给你两个字符串,让你构造出一个长度最小的字符串,且它的子序列包含这两个字符串。问它的长度,和多少种情况。
思路:
长度的话就是lena + lenb - LCS,这个比较明显。情况数比较难算。
dp[i][j][k]表示a字符串前i个字符 b字符串前j个字符构成长度为k的字符串有多少种情况。
(1)a[i] == b[i] 就是dp[i][j][k] = dp[i - 1][j - 1][k - 1] 。(2)a[i] != b[j] 的话分两种情况,a[i]在k位置和b[j]在k位置
感觉比较难。。。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 typedef long long LL; 6 char a[50], b[50]; 7 int _len[50][50]; 8 LL dp[50][50][100]; 9 10 int main() 11 { 12 int t; 13 scanf("%d", &t); 14 for(int ca = 1; ca <= t; ++ca) { 15 scanf("%s%s", a, b); 16 memset(_len, 0, sizeof(_len)); 17 memset(dp, 0, sizeof(dp)); 18 int len1 = strlen(a), len2 = strlen(b); 19 for(int i = 1; i <= len1; ++i) { 20 for(int j = 1; j <= len2; ++j) { 21 if(a[i - 1] == b[j - 1]) { 22 _len[i][j] = _len[i - 1][j - 1] + 1; 23 } else { 24 _len[i][j] = max(_len[i - 1][j], _len[i][j - 1]); 25 } 26 } 27 } 28 int len = len1 + len2 - _len[len1][len2]; 29 for(int i = 0; i <= len1; ++i) { 30 dp[i][0][i] = 1; //初始化 31 } 32 for(int j = 1; j <= len2; ++j) { 33 dp[0][j][j] = 1; //初始化 34 } 35 for(int i = 1; i <= len1; ++i) { 36 for(int j = 1; j <= len2; ++j) { 37 for(int k = 1; k <= len; ++k) { 38 if(a[i - 1] == b[j - 1]) { 39 dp[i][j][k] = dp[i - 1][j - 1][k - 1]; 40 } else { 41 dp[i][j][k] = dp[i - 1][j][k - 1] + dp[i][j - 1][k - 1]; //a字符串的第i位在第k位 + b字符串的第j位在第k位 42 } 43 } 44 } 45 } 46 printf("Case %d: %d %lld\n", ca, len, dp[len1][len2][len]); 47 } 48 return 0; 49 }