解决方法:
对于s的长度确定,很容易想到求出最长公共字串,length (s) = length (a) + length (b) - length (LCS);
关键在于个数的确定,学习大牛~~~
dp[i][j][k]中,表示构造了i长度的字符串,利用了a的前i个字符以及b的前j个字符,dp 就是当前状态下总的方案数, 考虑转移,要在后面继续扩充一个字符,如果a[j+1] = b[k+1],就可以转移到dp[i+1][j+1][k+1]的状态, 否则,可以转移到dp[i+1][j][k+1]或者dp[i+1][j+1][k];
注意:long long
AC代码如下:
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <algorithm>
using namespace std;
long long LCM( char a[], char b[] ){
int lengtha = strlen( a );
int lengthb = strlen( b );
int dp[50][50];
memset( dp, 0, sizeof( dp ) );
for( int i = 1; i <= lengtha; i++ ){
for( int j = 1; j <= lengthb; j++ ){
if( a[i-1] == b[j-1] ){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = max( dp[i-1][j], dp[i][j-1] );
}
}
}
return lengtha + lengthb - dp[lengtha][lengthb];
}
long long CNT( char a[], char b[], long long lcmab ){
long long dp[100][50][50];
memset( dp, 0, sizeof( dp ) );
dp[0][0][0] = 1;
int lengtha = strlen( a );
int lengthb = strlen( b );
for( int k = 0; k < lcmab; k++ ){
for( int i = 0; i <= lengtha; i++ ){
for( int j = 0; j <= lengthb; j++ ){
if( i == lengtha && !( j == lengthb ) ){
dp[k+1][i][j+1] += dp[k][i][j];
}else if( !( i == lengtha ) && j == lengthb ){
dp[k+1][i+1][j] += dp[k][i][j];
}else if( a[i] == b[j] ){
dp[k+1][i+1][j+1] += dp[k][i][j];
}else{
dp[k+1][i+1][j] += dp[k][i][j];
dp[k+1][i][j+1] += dp[k][i][j];
}
}
}
}
return dp[lcmab][lengtha][lengthb];
}
int main(){
int T, Case = 1;
char a[50], b[50];
long long lcm, cnt;
cin >> T;
while( T-- ){
cin >> a >> b;
lcm = LCM( a, b );
cnt = CNT( a, b, lcm );
cout << "Case " << Case++ << ": " << lcm << " " << cnt << endl;
}
return 0;
}