Uva--11081(动规,推导)
2014-08-24 13:27:15
Problem H
Strings
Given 3 strings of only lowercase letter you have to count the number of ways you can construct the third string by combining two subsequences from the first two strings.
After deleting 0 or more characters from a string we can get its subsequence. For example “a”, “b”, “c”, “ab”, “ac”, “bc” and “abc” all the strings are the subsequences of “abc”. A subsequence may also be empty.
Now suppose there are two subsequences “abc” and “de”. By combining them you can get the following strings “abcde”, “abdce”, “abdec”, “adbce”, “adbec”, “adebc”, “dabce”, “dabec”, “daebc” and “deabc”.
Input
The first line of the input contains a single integer T (0<T<271) indicating the number of test cases. Each test case contains 3 strings containing only lowercase characters. The lengths of the strings are between 1 and 60.
Output
For each test case output a single integer denoting the number of ways you can construct the third string from the first two string by the above way. The result may be very large. You should output the result%10007.
Sample Input Output for Sample Input
|
2 abc abc abc abbcd bccde abcde |
8 18
|
Problemsetter: Abdullah-al-Mahmud
Special Thanks: Md. Kamruzzaman
思路:解这个题参考了一位台湾选手的解题论文(附在最下面),我用dp[i][j][k]表示,用str1前i个字符,str2前j个字符来构成str3前k个字符的方案数。(论文中i,j,k含义有所不同,详情间论文),直接开三重循环进行递推,在考虑str3的第k个字符时要考虑它是从str1来的还是从str2来的,所用dp数组开3个,dp1[i][j][k]:表示str3中第k个字符来自str1中前i个字符的方案数,dp2[i][j][k]:表示str3中第k个字符来自str2中前j个字符的方案数,dp3[i][j][k]为dp1,dp2的和,即总方案数。
总的状态转移方程:
dp3[i][j][k] = dp1[i][j][k] + dp2[i][j][k];
if(str1[i - 1] == str3[k - 1]) : dp1[i][j][k] = dp1[i - 1][j][k] + dp3[i - 1][j][k - 1];(不用管str3第k - 1个字符来自str1还是str2,目前关心的是第k个来自哪,所以加dp3)
else : dp1[i][j][k] = dp1[i - 1][j][k];
if(str2[j - 1] == str3[k - 1]) : dp2[i][j][k] = dp2[i][j - 1][k] + dp3[i][j - 1][k - 1];
else : dp2[i][j][k] = dp[i][j - 1][k];
1 /************************************************************************* 2 > File Name: o.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Sun 24 Aug 2014 10:57:30 AM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 16 int t; 17 char s1[65],s2[65],s3[65]; 18 int len1,len2,len3; 19 int dp1[65][65][65]; 20 int dp2[65][65][65]; 21 int dp3[65][65][65]; 22 23 int main(){ 24 scanf("%d",&t); 25 while(t--){ 26 scanf("%s%s%s",s1,s2,s3); 27 len1 = strlen(s1); 28 len2 = strlen(s2); 29 len3 = strlen(s3); 30 memset(dp1,0,sizeof(dp1)); 31 memset(dp2,0,sizeof(dp2)); 32 memset(dp3,0,sizeof(dp3)); 33 // dp3[i][j][k] = sum(dp1[ti][j][k - 1]) (s1[ti] == s3[k - 1],1 <= ti <= i) 34 // + sum(dp2[i][tj][k - 1]) (s2[tj] == s3[k - 1],1 <= tj <= j) 35 for(int i = 0; i < 65; ++i){ 36 for(int j = 0; j < 65; ++j){ 37 dp1[i][j][0] = dp2[i][j][0] = dp3[i][j][0] = 1; 38 } 39 } 40 for(int i = 0; i <= len1; ++i){ 41 for(int j = 0; j <= len2; ++j){ 42 for(int k = 1; k <= len3; ++k){ 43 if(i){ 44 dp1[i][j][k] = dp1[i - 1][j][k]; 45 if(s1[i - 1] == s3[k - 1]) dp1[i][j][k] += dp3[i - 1][j][k - 1]; 46 } 47 if(j){ 48 dp2[i][j][k] = dp2[i][j - 1][k]; 49 if(s2[j - 1] == s3[k - 1]) dp2[i][j][k] += dp3[i][j - 1][k - 1]; 50 } 51 dp3[i][j][k] = (dp1[i][j][k] + dp2[i][j][k]) % 10007; 52 } 53 } 54 } 55 printf("%d\n",dp3[len1][len2][len3]); 56 } 57 return 0; 58 }
论文提供:http://blog.csdn.net/wall_f/article/details/8586976
附论文:http://par.cse.nsysu.edu.tw/~advprog/advprog2008/11081.doc

浙公网安备 33010602011771号