http://www.lightoj.com/volume_showproblem.php?problem=1013
题目大意:
给两个字符串,问最短的满足子串包含给的两个字符串的字符串的最短长度,以及最短长度的字符串的个数。
第一个问题就是简单的LCS,两个串长度和减去公共部分。
第二个问题要进行记忆话搜索来查找。dp(i,j,l)(第一个串i位,第二个串j位,总串l位)
转移方程
dp(i,j,l) = dp(i-1,j-1,l-1) (s1[i] = s2[j]时)
dp(i,j,l) = dp(i-1,j,l-1) + dp(i, j-1, l-1) (s1[i] != s2[j]时)
#include <stdio.h> #include <iostream> #include <string.h> #include <stdlib.h> #include <vector> #include <algorithm> #include <queue> #include <map> #include <string> #include <math.h> using namespace std; typedef pair<int,int> P; typedef long long LL; const int INF = 0x3f3f3f3f; const double PI = acos(-1.0); const double eps = 1e-9; const int N = 30 + 5; int t,n,m,len,kase = 0; int dp1[N][N]; LL dp2[N][N][2*N]; char s1[N],s2[N]; int lcs() { memset(dp1, 0, sizeof(dp1)); for(int i = 1; i <= n; i++) { for(int j = 1; j <= m; j++) { if(s1[i] == s2[j]) dp1[i][j] = dp1[i-1][j-1] + 1; else dp1[i][j] = max(dp1[i-1][j], dp1[i][j-1]); } } return dp1[n][m]; } LL dfs(int i, int j, int l) { LL &ans = dp2[i][j][l]; if(ans != -1) return ans; else if(l == 0) return i == 0 && j == 0; else if(i == 0) return ans = dfs(i, j-1, l-1); else if(j == 0) return ans = dfs(i-1, j, l-1); else if(s1[i] == s2[j]) return ans = dfs(i-1, j-1, l-1); else return ans = dfs(i-1, j, l-1) + dfs(i, j-1, l-1); } int main() { scanf("%d", &t); while(t--) { scanf("%s%s", s1+1, s2+1); n = strlen(s1+1); m = strlen(s2+1); len = n + m - lcs(); memset(dp2, -1, sizeof(dp2)); printf("Case %d: %d %lld\n", ++kase, len, dfs(n,m,len)); } return 0; }
时间: 2024-10-23 08:35:34