题目大意:给两个字符串a、b,找出一个最短的字符串c,使得这两个字符串都是c的子序列。只需找出p的最小长度和最小长度时的个数。
题目分析:与LCS问题类似。最小长度的状态转移方程,dp(i,j)=min(dp(i-1,j)+1,dp(i,j-1)+1,dp(i-1,j-1)+(a[i]==b[j])?1:2);个数也是差不多的求法,求所有最优决策对应的子问题的答案之和便是当前状态的答案总个数。
这是一道SB题,输入的字符串可能含有空格,用scanf读入字符串会WA、WA、WA!!!!!
代码如下:
# include<iostream> # include<cstdio> # include<cstring> # include<algorithm> using namespace std; const int INF=100000000; int dp[35][35],ans[35][35]; char p[35],q[35]; int main() { int T,cas=0; scanf("%d",&T); getchar(); while(T--) { cin.getline(p+1,35); cin.getline(q+1,35); int n=strlen(p+1); int m=strlen(q+1); dp[0][0]=0,ans[0][0]=1; for(int i=1;i<=m;++i){ dp[0][i]=i; ans[0][i]=1; } for(int i=1;i<=n;++i){ dp[i][0]=i; ans[i][0]=1; } for(int i=1;i<=n;++i){ for(int j=1;j<=m;++j){ if(p[i]==q[j]){ dp[i][j]=dp[i-1][j-1]+1; ans[i][j]=ans[i-1][j-1]; }else{ dp[i][j]=min(dp[i][j-1]+1,dp[i-1][j]+1); ans[i][j]=0; if(dp[i][j]==dp[i][j-1]+1) ans[i][j]+=ans[i][j-1]; if(dp[i][j]==dp[i-1][j]+1) ans[i][j]+=ans[i-1][j]; } } } printf("Case #%d: %d %d ",++cas,dp[n][m],ans[n][m]); } return 0; }