标签:
http://acm.hdu.edu.cn/showproblem.php?pid=5282
2 a b aa ab
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; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/lvshubao1314/article/details/46875293