UVA 11081 Strings(DP)

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

s1串,s2串得到s3串的方法:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<limits.h>
typedef long long LL;
using namespace std;
const int MOD=10007;
int f[70][70][70],f1[70][70][70],f2[70][70][70];
char s1[70],s2[70],s3[70];

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>s1+1>>s2+1>>s3+1;
        memset(f,0,sizeof(f));
        memset(f1,0,sizeof(f1));
        memset(f2,0,sizeof(f2));
        int len1=strlen(s1+1);
        int len2=strlen(s2+1);
        int len3=strlen(s3+1);
        for(int i=0;i<=len1;i++)
        {
            for(int j=0;j<=len2;j++)
                f[i][j][0]=f1[i][j][0]=f2[i][j][0]=1;
        }
        for(int k=1;k<=len3;k++)
        {
            for(int i=0;i<=len1;i++)
            {

                for(int j=0;j<=len2;j++)
                {
                    if(i)
                    {
                        f1[i][j][k]=f1[i-1][j][k];
                        if(s1[i]==s3[k])
                            f1[i][j][k]+=f[i-1][j][k-1];
                    }
                    if(j)
                    {
                        f2[i][j][k]=f2[i][j-1][k];
                        if(s2[j]==s3[k])
                            f2[i][j][k]+=f[i][j-1][k-1];
                    }
                    f[i][j][k]=(f1[i][j][k]+f2[i][j][k])%MOD;
                }
            }
        }
        cout<<f[len1][len2][len3]<<endl;
    }
    return 0;
}
时间: 2024-11-04 10:09:48

UVA 11081 Strings(DP)的相关文章

UVA 1371 - Period(DP)

6.4 一些说明 数据属性可以重写同名的方法属性.这是为了避免在大型系统中产生问题的意外名称冲突.所以用一些减少冲突的常用方法是很有效果的.常用的方法包括:大写字母方法名称,用唯一的字符串来做为数据属性的名称(可以是个下划线_)或者用动词命名方法和用名字命名数据属性. 数据属性就像和对象的普通用户一样可以被方法引用.换句话说,类不能用来实现纯净的数据类型.事实上,在python中不能强制数据隐藏,一切基于约定.(另一方面,如C中写的,python的实现可以做到完全隐藏实现细节并且在必要是可以控制

uva 10271 Chopsticks (DP)

uva 10271 ChopsticksA 题目大意:给出客人数K和筷子数量N(支),总人数M=客人数K + 8(还有家人).要找出M组筷子,每组包括3支筷子,每组都有一个badness值,badness值为每组中较小的两支筷子的差值.求怎样分组,才能使总差值最小. 解题思路:dp[i][j]表示使用第i支筷子,并已组成j组是的最小badness总值.在取筷子时,要注意在所有未被使用的筷子中,要有比选取的两根筷子更长的筷子. #include <cstdio> #include <cst

Codeforces 543C Remembering Strings(DP)

题意比较麻烦 见题目链接 Solution: 非常值得注意的一点是题目给出的范围只有20,而众所周知字母表里有26个字母.于是显然对一个字母进行变换后是不影响到其它字符串的. 20的范围恰好又是常见状压DP的范围,所有状态压缩后用DP[sta]代表对应位的字符串已经满足要求的最小花费. 转移的时候,对一个字符串,逐列判断使它满足条件的最小花费,记录使用这个策略对sta的影响. 即对同一列有两种情况,直接变换该字符串的这一位,或者变换这一列的sum-1个有相同字符的位置(去掉代价最大的). #in

【UVa】Jump(dp)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4198 约瑟夫变形 根据f(n)=(f(n-1)+m)%n 因为是求倒数第几个 那么我们只要求出f(倒数第几个)的值然后再带进去即可. (没理解的自行面壁..) 而f(倒数第几个)=(m-1)%倒数第几个 然后就行了.. #include <cstdio> #include <

Uva 10465-Homer Simpson(DP)

题目链接:点击打开链接 DAG上的最长路. 题意:相当于给两种硬币的面值,每种可以用无限次,问恰好组成S 最多能用多少个硬币.如果不能恰好组成S,输出最大能组成的面值x(x<S)所需的最大硬币数 和 S-x. #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <string> #include <cctype&

UVA 10163-Storage Keepers(DP)

题目大意:有N(1<=N<=100)个仓库需要看管,有M(1<=M<=30)名应聘者,每个人有能力属性Pi(1<=Pi<=1000).所有仓库都是一样的,每个仓库只能被一人看守,一人可看守多个仓库,当一人看守u个仓库时,每个仓库的安全度为Uj=Pi/u,总安全度为min Uj.雇佣一个能力值为Pi的人需要花费Pi元.求最大的总安全度,和在这样的情况下的最小花费. 先dp一次,求出可能的最大总安全度max,再次dp,求出在安全度为max下的最小花费. 第一次dp:用d[i

UVA 1366-Martian Minging(DP)

题目大意:有一个n(1<=n<=500)行m(1<=m<=500)列的网格,每个网格有两种矿,yeyenum和bloggium,在网格的西边是yeyenum的精炼厂,北边是bloggium的精炼厂,每个网格有一定数量的两种矿,现在要安排一个传送带系统,传送带只能由南向北或者由东向西,传送带同方向的可以连续传,只有传到相应精炼厂才是有效的,问许多能拿到多少矿. 用d[i][j]表示到第i行第j列时,前i行j列能产生的最大的矿数量,用a[i][j]表示在第i行从第1列加到第j列的yey

UVA 473-Raucous Rockers(DP)

题目大意:有n首歌,m个光盘,每个光盘最多能放t时间的歌,给出每首歌的长度,必须按顺序录入光盘(可以选择不录某几首歌),最多能录多少首歌. 用d[i][j][0]表示前i首歌,放j首,最少用多少个光盘,用d[i][j][1]表示前i首歌,放j首,在光盘最少的前提下,最后一个光盘可以剩余的最多容量.根据是否放第i首歌完成递推. 这样递推是正确的,因为前i首歌,放j首的情况下,最佳的情况就是尽量少的用光盘,并且使得最后一个光盘容量尽量大(例如如果用的光盘数多一些,并且最后一个光盘的容量更大一些,这样

Codeforces Round #358 (Div. 2) D. Alyona and Strings(DP)

题目链接:点击打开链接 思路: 类似于LCS, 只需用d[i][j][k][p]表示当前到了s1[i]和s2[j], 形成了k个子序列, 当前是否和上一个字符和上一个字符相连形成一个序列的最长序列和. 细节参见代码: #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <string> #include <vector&