码迷,mamicode.com
首页 > 其他好文 > 详细

hdu5282 最长公共子序列的变形

时间:2015-07-14 13:45:05      阅读:171      评论:0      收藏:0      [点我收藏+]

标签:

http://acm.hdu.edu.cn/showproblem.php?pid=5282

Problem Description
Xuejiejie loves strings most. In order to win the favor of her, a young man has two strings XY to Xuejiejie. Xuejiejie has never seen such beautiful strings! These days, she is very happy. But Xuejiejie is missish so much, in order to cover up her happiness, she asks the young man a question. In face of Xuejiejie, the young man is flustered. So he asks you for help.

The question is that :
Define the L as the length of the longest common subsequence of X and Y.( The subsequence does not need to be continuous
in the string, and a string of length L has 2L subsequences containing the empty string ). Now Xuejiejie comes up with all subsequences of length L of string X, she wants to know the number of subsequences which is also the subsequence of string Y.
 

Input
In the first line there is an integer T, indicates the number of test cases.

In each case:

The first line contains string X, a non-empty string consists of lowercase English letters.

The second line contains string Y, a non-empty string consists of lowercase English letters.

1|X|,|Y|1000|X| means the length of X.
 

Output
For each test case, output one integer which means the number of subsequences of length L of X which also is the subsequence of string Y modulo 109+7.
 

Sample Input
2 a b aa ab
 

Sample Output
1 2
/**
hdu5282 最长公共子序列的变形
题目大意:给定两个字符串,求二者的最长公共子序列,在a中出现过的,有多少是b的子序列
解题思路:来自官方题解。
          首先我们用O(n2)的动态规划算法处理出dp数组,dp[i][j]表示X串的前i个字符和Y
          串的前j个字符的最长公共子序列的长度,在这个基础上我们再进行一个动态规划。
          用f[i][j]表示在X串的前i个字符中,有多少个长度为dp[i][j]的子序列在Y的前j个
          字符中也出现了。转移:若dp[i?1][j]==dp[i][j],则f[i][j]+=f[i?1][j],表示i
          这个字符不选;再考虑选i这个字符,找到Y串前j个字符中最靠后的与X[i]匹配的字
          符的位置,设为p,若dp[i?1][p?1]+1==dp[i][j],则f[i][j]+=f[i?1][p?1]。最终
          的答案即为f[n][m]。复杂度O(n2)。

*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
const int maxn=1005;
int dp[maxn][maxn],n,m,wei[maxn][maxn];
char a[maxn],b[maxn];
LL f[maxn][maxn];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s%s",a,b);
        n=strlen(a);
        m=strlen(b);
        memset(dp,0,sizeof(dp));
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<m; j++)
            {
                dp[i+1][j+1]=max(dp[i+1][j],dp[i][j+1]);
                if(a[i]==b[j])
                    dp[i+1][j+1]=max(dp[i][j]+1,dp[i+1][j+1]);
            }
        }
        memset(wei,0,sizeof(wei));
        for(int i=1;i<=m;i++)
        {
            for(int j=0;j<26;j++)
            {
                wei[i][j]=wei[i-1][j];
            }
            wei[i][b[i-1]-'a']=i;
        }
        memset(f,0,sizeof(f));
        for(int i=0;i<=n;i++)
        {
            for(int j=0;j<=m;j++)
            {
                if(dp[i][j]==0)
                {
                    f[i][j]=1;
                    continue;
                }
                if(dp[i-1][j]==dp[i][j])
                {
                    f[i][j]=(f[i][j]+f[i-1][j])%mod;
                }
                int p=wei[j][a[i-1]-'a'];
                if(p)
                {
                    if(dp[i-1][p-1]+1==dp[i][j])
                    {
                        f[i][j]=(f[i][j]+f[i-1][p-1])%mod;
                    }
                }
            }
        }
        printf("%I64d\n",f[n][m]);
    }
    return 0;
}


版权声明:本文为博主原创文章,未经博主允许不得转载。

hdu5282 最长公共子序列的变形

标签:

原文地址:http://blog.csdn.net/lvshubao1314/article/details/46875293

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!