研究了好久,也没怎么明白…
对DP的理解真的不够….只能勉强记住已经知道的题型
放个别人的解析,感觉是写的最全的了
我们可以模仿LCS的构建方法来思考这个问题 c[i][j]表示a串前i个元素和b串前j个元素所能得到的方案数。l[i][j]表示LCS的长度
若a[i]=b[j],那么c[i][j]=c[i-1][j-1],即a串前i-1个元素和b串前j-1个元素得到的组合串的末尾加上一个相同的元素a[i],那么得到的新的组合串的个数还是和之前的组合串的个数一样
若a[i]!=b[j], l[i][j]=max { l[i-1][j] , l[i][j-1]}
若l[i-1][j]>l[i][j-1],那说明从l[i-1][j]这种状态开始构建才能得到最终的LCS同时最终的组合串才不能漏掉共有的元素,所以c[i][i]=c[i-1][j],即在a串i-1个元素和b串j个元素组成的组合串的后面加上a[i],那么得到的新的组合串的个数和之前的组合串的个数是相同的
若l[i][j-1]>l[i-1][j],道理和上面是一样的,所以c[i][j]=c[i][j-1],相当于在之前的组合串后面加上元素b[j],得到新的组合串的个数不变
若l[i][j-1]=l[i-1][j],说明从两种状态都是能得到最终的LCS并且最终的组合串不会漏掉任何相同的公共元素,所以c[i][j]=c[i-1][j]+c[i][j-1] , 即用a串的i-1个元素和b串的j个元素组成的组合串的最后加上a[i]得到新的组合串和之前的组合串个数相同,另外用a串的i个元素和b串的的j-1个元素组成的组合串的最后加上b[j]得到新的组合串和之前的组合串个数相同,那么就是两者之和(http://www.cnblogs.com/scau20110726/archive/2012/10/01/2709781.html)
剩下的就是注意空行
gets已经不能用了所以getline
问了一个大佬
大佬直接就看出是DP
然后举了一个例子归纳就得出了状态转移方程。。。。。
这或许就是大佬吧.jpg
#include <cstdio>
#include <cstring>
#include <iostream>
#define N 50
char str1[ N ];
char str2[ N ];
int len1, len2;
int length[ N ][ N ];
long long variety[ N ][ N ];
int main () {
int T;
scanf ( "%d", &T );
getchar ();
for ( int t = 1; t <= T; t++ ) {
std::cin.getline ( str1 + 1, N - 1 );
std::cin.getline ( str2 + 1, N - 1 );
len1 = strlen ( str1 + 1 );
len2 = strlen ( str2 + 1 );
memset ( length, 0, sizeof ( length ) );
memset ( variety, 0, sizeof ( variety ) );
for ( int i = 0; i <= len1; i++ )
variety[ i ][ 0 ] = 1;
for ( int i = 0; i <= len2; i++ )
variety[ 0 ][ i ] = 1;
for ( int i = 1; i <= len1; i++ ) {
for ( int j = 1; j <= len2; j++ ) {
if ( str1[ i ] == str2[ j ] ) {
length[ i ][ j ] = length[ i - 1 ][ j - 1 ] + 1;
variety[ i ][ j ] = variety[ i - 1 ][ j - 1 ];
}
else {
if ( length[ i - 1 ][ j ] > length[ i ][ j - 1 ] ) {
length[ i ][ j ] = length[ i - 1 ][ j ];
variety[ i ][ j ] = variety[ i - 1 ][ j ];
} else if ( length[ i - 1 ][ j ] == length[ i ][ j - 1 ] ) {
length[ i ][ j ] = length[ i - 1 ][ j ];
variety[ i ][ j ] =
variety[ i - 1 ][ j ] + variety[ i ][ j - 1 ];
} else {
length[ i ][ j ] = length[ i ][ j - 1 ];
variety[ i ][ j ] = variety[ i ][ j - 1 ];
}
}
}
}
printf ( "Case #%d: %d %lld\n", t, len1 + len2 - length[ len1 ][ len2 ],
variety[ len1 ][ len2 ] );
}
return 0;
}