uva11081 - Strings

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值