先求个最长公共子序列的长度,dp1[i][j]表示装下X[1...i],Y[1...j]这两个串需要的最小长度。
X[i] == Y[j],dp[i][j] = dp[i-1][j-1] + 1;
X[i] != Y[j], dp[i][j] = min(dp[i-1][j],dp[i][j-1]) + 1;
然后就是dp2[i][j][k]表示X串的前i个和Y的前j个构成长度为k的串的方法数。
X[i] == Y[j], dp2[i][j] += dp2[i-1][j];
X[i] != Y[j], if (dp[i-1][j] + 1 == dp[i][j]) dp2[i][j] += dp2[i-1][j];//这个地方是因为X的前i-1个和Y的前j个需要的最小长度 + 1 == X的前i个和Y的前J个长度,说明X的第i个字符可以添加在X的前i-1个和Y的前j个串的后面,下面也是一样的。
if (dp[i][j-1] + 1 == dp[i][j]) dp2[i][j] += dp2[i][j-1];
/***************************************** Author :Crazy_AC(JamesQi) Time :2015 File Name : *****************************************/ // #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <algorithm> #include <iomanip> #include <sstream> #include <string> #include <stack> #include <queue> #include <deque> #include <vector> #include <map> #include <set> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <climits> using namespace std; #define MEM(x,y) memset(x, y,sizeof x) #define pk push_back typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> ii; const double eps = 1e-10; const int inf = 1 << 30; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int maxn = 32; int dp1[maxn][maxn]; LL dp2[maxn][maxn]; int len1,len2; char s1[maxn],s2[maxn]; int lcs(){ for (int i = 1;i <= len1;++i){ for (int j = 1;j <= len2;++j){ if (s1[i-1] == s2[j-1]) dp1[i][j] = dp1[i-1][j-1] + 1; else{ dp1[i][j] = min(dp1[i-1][j],dp1[i][j-1]) + 1; } } } return dp1[len1][len2]; } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int t, icase = 0; for (int i = 0;i < maxn;++i){ dp1[0][i] = dp1[i][0] = i; dp2[i][0] = dp2[0][i] = 1; } scanf("%d",&t); while(t--){ scanf("%s",s1); scanf("%s",s2); len1 = strlen(s1); len2 = strlen(s2); int ans = lcs(); for (int i = 1;i <= len1;++i){ for (int j = 1;j <= len2;++j){ dp2[i][j] = 0; if (s1[i-1] == s2[j-1]) dp2[i][j] += dp2[i-1][j-1]; else{ if (dp1[i][j-1] + 1 == dp1[i][j]) dp2[i][j] += dp2[i][j-1]; if (dp1[i-1][j] + 1 == dp1[i][j]) dp2[i][j] += dp2[i-1][j]; } } } printf("Case %d: ", ++icase); printf("%d ",ans); printf("%lld\n",dp2[len1][len2]); } return 0; }
X[i] == Y[j], dp[i][j][k + 1] = dp[i-1][j-1][k];
X[i] != Y[j], dp[i][j][k + 1] += dp[i-1][j][k] + dp[i][j-1][k];
/***************************************** Author :Crazy_AC(JamesQi) Time :2015 File Name : *****************************************/ // #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <algorithm> #include <iomanip> #include <sstream> #include <string> #include <stack> #include <queue> #include <deque> #include <vector> #include <map> #include <set> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <climits> using namespace std; #define MEM(x,y) memset(x, y,sizeof x) #define pk push_back typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> ii; const double eps = 1e-10; const int inf = 1 << 30; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int maxn = 32; LL dp[maxn*2][maxn][maxn]; char s1[maxn], s2[maxn]; int dp1[maxn][maxn]; int LCS (int lenstr,int lench) {//返回LCS的长度 memset(dp1,0,sizeof(dp1)); int k; for (int i=1;i<=lenstr;i++) { k=i&1; for (int j=1;j<=lench;j++) if (s1[i-1] == s2[j-1]) dp1[k][j]=dp1[k^1][j-1]+1; else dp1[k][j]=max(dp1[k][j-1],dp1[k^1][j]); } return dp1[k][lench]; } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int t, icase = 0; scanf("%d",&t); while(t--){ scanf("%s",s1); scanf("%s",s2); int len1 = strlen(s1),len2 = strlen(s2); memset(dp, 0,sizeof dp); int ans = len1 + len2 - LCS(len1,len2); dp[0][0][0] = 1; for (int k = 0;k <= ans;++k){ for (int i = 0;i <= len1;++i){ for (int j = 0;j <= len2;++j){ if (s1[i] == s2[j]){ dp[k+1][i+1][j+1] += dp[k][i][j]; }else{ dp[k+1][i][j+1] += dp[k][i][j]; dp[k+1][i+1][j] += dp[k][i][j]; } } } } printf("Case %d: ", ++icase); cout << ans << ' ' << dp[ans][len1][len2] << endl; } return 0; }