Problem H
Strings
Input: Standard Input
Output: Standard Output
Given 3 strings of only lowercaseletter you have to count the number of ways you can construct the third stringby combining two subsequences from the first two strings.
After deleting 0 or morecharacters 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 twosubsequences “abc” and “de”. By combining them youcan get the following strings “abcde”, “abdce”,“abdec”, “adbce”, “adbec”, “adebc”, “dabce”, “dabec”, “daebc” and “deabc”.
Input
The first line of the inputcontains a single integer T (0<T<271) indicating the number of testcases. Each test case contains 3 stringscontaining only lowercase characters. The lengths of the strings are between 1and 60.
Output
For each test case output asingle integer denoting the number of ways you can construct the third stringfrom the first two string by the above way. The result may be very large. Youshould output the result%10007.
SampleInput Outputfor Sample Input
2 abc abc abc abbcd bccde abcde | 8 18
|
从前两个串里选出子串(空的也算),组合出目标串,有多少种选择方法。
可以看出目标串的最后一个字母一定是一个子串中的最后一个字母。这道题想的都差不多了,已经想出用dp[i][j][k]表示第1个串前i个字符和第2个串前j个字符组合成目标串前k个字符的情况数,状态转移方程也想了,但就是不知道后面的状态怎么跟前面的联系起来。。如果是dp[i][j][k]=dp[i-1][j][k]+dp[i][j-1][k]肯定是不对的,因为会重复。。网上查了看人家是用dp1[i][j][k]表示目标串最后一个字母在第1个串中,dp2[i][j][k]表示目标串最后一个字母在第2个串中,巧妙的方法。。
#include<cstring>
#include<cstdio>
#include<iostream>
#include<climits>
#include<cmath>
#include<algorithm>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
char a[70],b[70],c[70];
int dp1[70][70][70],dp2[70][70][70],dp[70][70][70];
int main(){
freopen("in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--){
scanf("%s%s%s",a,b,c);
memset(dp,0,sizeof(dp));
int i,j,k,p,L1=strlen(a),L2=strlen(b),L3=strlen(c);
memset(dp,0,sizeof(dp));
memset(dp1,0,sizeof(dp1));
memset(dp2,0,sizeof(dp2));
for(i=0;i<=L1;i++)
for(j=0;j<=L2;j++) dp[i][j][0]=dp1[i][j][0]=dp2[i][j][0]=1;
for(k=1;k<=L3;k++)
for(i=0;i<=L1;i++)
for(j=0;j<=L2;j++){
if(i){
dp1[i][j][k]=dp1[i-1][j][k];
if(a[i-1]==c[k-1]) dp1[i][j][k]+=dp[i-1][j][k-1];
dp1[i][j][k]%=10007;
}
if(j){
dp2[i][j][k]=dp2[i][j-1][k];
if(b[j-1]==c[k-1]) dp2[i][j][k]+=dp[i][j-1][k-1];
dp2[i][j][k]%=10007;
}
dp[i][j][k]=(dp1[i][j][k]+dp2[i][j][k])%10007;
}
printf("%d\n",dp[L1][L2][L3]);
}
return 0;
}