light oj 1013 LCS 应用

来源:互联网 发布:天界五行进阶数据 编辑:程序博客网 时间:2024/04/18 14:46

题意:给定两个字符串A,B,要求求一个字符串S,使得A,B是S 的子串,求S 的最小长度,以及在此长度下有多少种构成S 的方案。

LCS的变形,S的最小长度肯定是A+B的长度-A和B的最长公共组序列的长度。之后的方案用DP思想去写就可以了。QAQ 我也是看了题解才会写的。

先用lcs 去求A和B 的最长公共子序列。

然后dp[i][j][k]表示构造了i长度的字符串,在利用了A串的前j个字符和B串的前K个字符,此状态下的解决方案总数,那么后面的方程就和LCS 一样了

如果A[j]==B[k],那么dp[i+1][j+1][k+1] += dp[i][j][k]; 不然就转移到右边和下边的状态,dp[i+1][j][k+1] += dp[i][j][k]; dp[i+1][j+1][k] += dp[i][j][k]; 原理类似于LCS。

 

#include <stdio.h>#include <string.h>#include <algorithm>#pragma warning (disable :4996)using namespace std;const int Max = 33;int lcs[Max][Max];long long dp[Max << 1][Max][Max];char str1[Max], str2[Max];int LCS(int lenstr1, int lenstr2){memset(lcs, 0, sizeof(lcs));for (int i = 1; i <= lenstr1; i++){for (int j = 1; j <= lenstr2; j++){if (str1[i-1] == str2[j-1])lcs[i][j] = lcs[i - 1][j - 1] + 1;elselcs[i][j] = max(lcs[i - 1][j], lcs[i][j - 1]);}}return lcs[lenstr1][lenstr2];}int main(){int T;scanf("%d ", &T);for (int t = 1; t <= T; t++){memset(dp, 0, sizeof(dp));dp[0][0][0] = 1;gets(str1);gets(str2);int n, m, lenlcs;n = strlen(str1);m = strlen(str2);lenlcs = LCS(n, m);int ans = n + m - lenlcs;for (int i = 0; i <= ans; i++)for (int j = 0; j <= n; j++)for (int k = 0; k <= m;k++)if (dp[i][j][k])if (str1[j] != str2[k]){dp[i + 1][j][k + 1] += dp[i][j][k];dp[i + 1][j + 1][k] += dp[i][j][k];}else dp[i + 1][j + 1][k + 1] += dp[i][j][k];printf("Case %d: %d %lld\n", t, ans, dp[ans][n][m]);}return 0;}

0 0
原创粉丝点击