http://acm.hdu.edu.cn/showproblem.php?pid=5282
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.
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.
/**
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; }