a | b | f | c | a | b | ||
0 | 0 | 0 | 0 | 0 | 0 | 0 | |
b | 0 | 0 | 1 | 1 | 1 | 1 | 1 |
a | 0 | 1 | 1 | 1 | 1 | 1 | 2 |
f | 0 | 1 | 1 | 2 | 2 | 2 | 2 |
c | 0 | 1 | 1 | 2 | 3 | 3 | 3 |
a | 0 | 1 | 2 | 2 | 3 | 4 | 4 |
b | 0 | 1 | 2 | 2 | 3 | 4 | 5 |
本题每个a[i]==b[j]的点都会对以该点位左上角的方阵的全部元素产生+1的效果
理解了这个本质其实直接写个函数使其产生对作用范围内全部元素+1的效果 然后遍历全部input 不过这样的更新量过大 更好的方法就是直接找相邻元素间的递推关系 思维上稍微复杂点 不过程序上就更快了
上述表格里 第一个零元素对应的是f[0][0] 而f[i][j]则表示a的前i个元素和b的前j个元素之间的最长公共子序列的长度 初始条件是f[0][*]和f[*][0]做全为0 实际上是冗余 因为这些数值没有与元素有实际的对应关系 而是而是假设其中一个输入为null时的情况
// HDOJ_1159.cpp : Common Subsequence
#include <iostream>
using namespace std;
char a[1002];
char b[1002];
int f[1002][1002];
int main()
{
int i, j;
int alen, blen;
while ( scanf("%s %s",a+1,b+1)!=EOF ){
alen = strlen(a+1);
blen = strlen(b+1);
for( i=0; i<=alen; i++ )
for ( j=0; j<alen; j++ )
f[i][j] = 0;
for( i=1; i<=alen; i++ )
for( j=1; j<=blen; j++ ){
if( a[i]==b[j] )
f[i][j] = f[i-1][j-1]+1;
else
f[i][j] = max(f[i-1][j],f[i][j-1]);
}
cout << f[alen][blen] << endl;
for( i=1; i<=alen; i++ ){
for( j=1; j<=blen; j++ )
cout << f[i][j] << " ";
cout << endl;
}
}
//system("pause");
return 0;
}
之前用C++输入风格写了个程序 自己这边跑的很好 结果OJ上总RE 后来参照网上其他人的程序才发现 貌似是大数组需要放到main外面声明 不过这样就没法动态分配数组了 至少以我目前的知识不知道如何不浪费内存
如果不是有极长的输入的话 下面的程序也是能用的 另外虽然递推关系没变 不过当时没有让f[0][*]和f[*][0]做全为0的冗余 而是让f的第一行和第一列的元素在相同时为1不同时为0 并作为初始条件 这样导致一部分f[i][j]并不是a的前i+1个元素和b的前j+1个元素之间的最长公共子序列的长度 不过最终的总长度求值是正确的
[picture holder======]
// HDOJ_1159.cpp : Common Subsequence
#include <iostream>
#include <string>
using namespace std;
int main()
{
int i, j;
string a,b;
int alen, blen;
while ( cin >> a >> b ){ //cin读入string需要<string>头文件
alen = a.length();
blen = b.length();
//cout << alen << " " << blen << endl; //校验长度是否正确
int **f = new int*[alen]; //动态分配二维数组
for( i=0; i<alen; i++ )
f[i] = new int[blen];
//memset( f, 0, sizeof(f) ); //memset用在这里会出错 回头找下原因
for( i=0; i<alen; i++ )
for( j=0; j<blen; j++ )
f[i][j] = 0;
for( i=0; i<alen; i++ )
if( a[i]==b[0] ) f[i][0] = 1;
for( j=0; j<blen; j++ )
if( a[0]==b[j] ) f[0][j] = 1; //上面两个for初始化第一行和第一列
for( i=1; i<alen; i++ )
for( j=1; j<blen; j++ ){
if( a[i]==b[j] )
f[i][j] = f[i-1][j-1]+1;
else
f[i][j] = max(f[i-1][j],f[i][j-1]);
}
cout << f[alen-1][blen-1] << endl;
for( i=0; i<alen; i++ ){
for( j=0; j<blen; j++ )
cout << f[i][j] << " ";
cout << endl;
}
}
//system("pause");
return 0;
}