Light OJ 1013 Love Calculator(DP)

 题目大意:

   给你两个字符串A,B 要求一个最短的字符串C,使得A,B同时为C的子串。 问C最短长度是多少? C有多少种?

题目分析:

  做这道题目的时候自己并没有推出来,看了网上的题解。

1.dp[C串的长度][包含A的字符个数][包含B的字符个数] = 种类数

状态转移:如果 A[i] == B[j] 那么 dp[k][i][j] = dp[k-1][i-1][j-1]. 就是说我最后一个字符是相同的那么我只要放一个就可以了。

     如果 A[i] !=  B[j] 那么 dp[k][i][j] = dp[k-1][i-1][j] + dp[k-1][i][j-1].最后一个字符我们要么放A[i] 要么放 B[j] 就这两种情况了。

然后关于找最短的,就可以在 dp[k][lenA][lenB] 种找到最小的k即可。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL;
#define Max(a,b) (a>b?a:b)
const int INF = 1e9+7;
const int maxn = 55;
const int MOD = 9973;
LL dp[maxn*2][maxn][maxn];///dp[总长度][包含i个A串字符][包含j个B串字符]
char A[maxn], B[maxn];

int main()
{
    int T, cas = 1;
    scanf("%d", &T);
    while(T --)
    {
        scanf("%s %s", A, B);
        int lenA = strlen(A);
        int lenB = strlen(B);
        memset(dp, 0, sizeof(dp));
        for(int i=0; i<=lenA; i++) dp[i][i][0] = 1;
        for(int i=0; i<=lenB; i++) dp[i][0][i] = 1;

        for(int i=1; i<=lenA+lenB; i++)
        for(int j=1; j<=lenA; j++)
        for(int k=1; k<=lenB; k++)
        {
            if(A[j-1] == B[k-1])
                dp[i][j][k] += dp[i-1][j-1][k-1];
            else
                dp[i][j][k] += dp[i-1][j-1][k] + dp[i-1][j][k-1];
        }
        int k;
        for(k = 1; k<=lenA+lenB; k ++)
        {
            if(dp[k][lenA][lenB])
                break;
        }
        printf("Case %d: %d %lld
", cas ++, k, dp[k][lenA][lenB]);
    }
    return 0;
}
代码在此
原文地址:https://www.cnblogs.com/chenchengxun/p/4903430.html