lightoj 1013 - Love Calculator

先求个最长公共子序列的长度,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;
}

或者就是dp[i][j][k]表示X的前i个字符heY的前j个字符构成长度为k的字符串的方法数。

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;
}

点击打开链接

你可能感兴趣的:(dp,lightoj)