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即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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\n", cas ++, k, dp[k][lenA][lenB]); } return 0; }