hdu5282 最长公共子序列的变形

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 X, Y 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;
}

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

时间: 2024-10-05 14:21:07

hdu5282 最长公共子序列的变形的相关文章

poj1159--Palindrome(dp:最长公共子序列变形 + 滚动数组)

Palindrome Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 53414   Accepted: 18449 Description A palindrome is a symmetrical string, that is, a string read identically from left to right as well as from right to left. You are to write a

UVA 10723--Cyborg Genes+最长公共子序列变形

题目链接:点击进入 首先对于长度最短的情况是很容易确定的,只需要用两个字符串的长度和减去他们的最长公共子序列长度.然后比较麻烦的就是合乎要求的字符串的个数,其实我们也可以用类似于最长公共子序列的dp来求. 设dp[i][j]表示str1的前i个字符和str2的前j个字符所得到的满足要求的字符串,则如果str[i]==str[j],则dp[i][j]+=dp[i-1][j-1]; 否则就要根据i,j这两个位置上的最长公共子序列长度进行讨论,具体见代码. 代码如下: #include<iostrea

hdu1243(最长公共子序列变形)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1243 分析:dp[i][j]表示前i个子弹去炸前j个恐怖分子得到的最大分.其实就是最长公共子序列加每个字母值为1,这里每个字母代表的值变化了一下. 状态转移方程:if(s1[i-1]==s2[j-1])dp[nxt][j]=dp[cur][j-1]+val[s1[i-1]];                              else  dp[nxt][j]=max(dp[nxt][j-1]

51Nod 1092 回文字符串 | 最长公共子序列变形

求字符串和其逆的最长公共子序列,需要添加的字符数就为长度-最长公共子序列长 #include "stdio.h" #include "string.h" #define maxn 1005 char s[maxn],s1[maxn]; int dp[maxn][maxn]; int main() { int n=0,i,j,len; scanf("%s",s); len=strlen(s); strcpy(s1,s); strrev(s1); f

POJ 2250(最长公共子序列 变形)

Description In a few months the European Currency Union will become a reality. However, to join the club, the Maastricht criteria must be fulfilled, and this is not a trivial task for the countries (maybe except for Luxembourg). To enforce that Germa

最长公共子序列(LCS)

最长公共子序列,英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列.而最长公共子串(要求连续)和最长公共子序列是不同的.       最长公共子序列是一个十分实用的问题,它可以描述两段文字之间的"相似度",即它们的雷同程度,从而能够用来辨别抄袭.对一段文字进行修改之后,计算改动前后文字的最长公共子序列,将除此子序列外的部分提取出来,

最长公共子序列的代码实现

关于最长公共子序列(LCS)的相关知识,http://blog.csdn.net/liufeng_king/article/details/8500084 这篇文章讲的比较好,在此暂时不再详说. 以下是我代码实现两种方式:递归+递推: 1 #include <bits/stdc++.h> 2 using namespace std; 3 int A[100]; 4 int B[100]; 5 6 //int B[]={2,3,5,6,9,8,4}; 7 int d[100][100]={0};

NYOJ 36 &amp;&amp;HDU 1159 最长公共子序列(经典)

链接:click here 题意:tip:最长公共子序列也称作最长公共子串(不要求连续),英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列. 输入 第一行给出一个整数N(0<N<100)表示待测数据组数 接下来每组数据两行,分别为待测的两组字符串.每个字符串长度不大于1000. 输出 每组测试数据输出一个整数,表示最长公共子序列长度.每组

poj1159 Palindrome(最长公共子序列)

Palindrome Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 52966   Accepted: 18271 Description A palindrome is a symmetrical string, that is, a string read identically from left to right as well as from right to left. You are to write a