Lightoj1013【DP_LCS】
题意:
给你两个字符串,让你求一个最短字符串,其中存在给出串的种类;
求这个字符串的长度和种类;
思路:
//dp[i,j,k]表示前i个字符,包含s1串前j个字母,包含s2串前k个字符时的方案数。
//按照一定的顺序,碰到相同元素只会留一个,不同元素这个位置就有两种情况
给你两个字符串,让你求一个最短字符串,其中存在给出串的种类;
求这个字符串的长度和种类;
思路:
//dp[i,j,k]表示前i个字符,包含s1串前j个字母,包含s2串前k个字符时的方案数。
//按照一定的顺序,碰到相同元素只会留一个,不同元素这个位置就有两种情况
#include<cstdio> #include<math.h> #include<queue> #include<map> #include<string> #include<string.h> #include<iostream> #include<algorithm> using namespace std; typedef long long LL; const int INF=0x3f3f3f3f; const LL mod=1e9+7; const int N=50; char s1[N],s2[N]; int len[N][N]; LL dp[100][N][N]; int LCS() { int n,m; n=strlen(s1+1); m=strlen(s2+1); memset(len,0,sizeof(len)); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(s1[i]!=s2[j]) len[i][j]=max(len[i-1][j],len[i][j-1]); else len[i][j]=len[i-1][j-1]+1; } } return n+m-len[n][m]; } LL solve(int length) { int n,m; n=strlen(s1+1); m=strlen(s2+1); memset(dp,0,sizeof(dp)); dp[0][0][0]=1; for(int i=1;i<=length;i++) { dp[i][0][i]=1; dp[i][i][0]=1; for(int j=1;j<=min(n,i);j++) { for(int k=1;k<=min(m,i);k++) { if(s1[j]==s2[k]) 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]; } } } return dp[length][n][m]; } int main() { int T,cas=1; int ans1; LL ans2; scanf("%d",&T); while(T--) { scanf("%s%s",s1+1,s2+1); ans1=LCS(); ans2=solve(ans1); printf("Case %d: %d %lld\n",cas++,ans1,ans2); } return 0; }