您的位置:首页 > 编程语言

编程练习-动态规划(最长公共子序列LCS)

2012-02-03 20:19 483 查看
程序代码如下:

#include <stdio.h>
#include <vector>
#include <boost/scoped_ptr.hpp>
template<typename T>
class DualArrayInternal {
public:
DualArrayInternal(T* array_data, size_t column_num) : array_data_(array_data), column_num_(column_num) {
}
T& operator[](size_t y) {
return array_data_[x_ * column_num_ + y];
}
const T& operator[](size_t y) const {
return array_data_[x_ * column_num_ + y];
}
void SetX(size_t x) {
x_ = x;
}
private:
size_t x_;
T* array_data_;
size_t column_num_;
};
template<typename T>
class DualArray {
public:
DualArray(T* array_data, size_t column_num) : internal_(array_data, column_num) {}
DualArrayInternal<T>& operator[](size_t x) {
internal_.SetX(x);
return internal_;
}
const DualArrayInternal<T>& operator[](size_t x) const{
const_cast<DualArray*>(this)->internal_.SetX(x);
return internal_;
}
private:
DualArrayInternal<T> internal_;
};
void Print(int value) {
printf("%c", value);
}
template<typename T, typename PrintFun>
void PrintSequence(const std::vector<T>& array1,  const DualArray<char>& path_direction, const size_t i, const size_t j, PrintFun print_fun) {
if (i == 0 || j == 0) {
return;
}
if (path_direction[i][j] == 'S') {
PrintSequence(array1, path_direction, i - 1, j - 1, print_fun);
print_fun(array1[i - 1]);
} else if(path_direction[i][j] == 'U') {
PrintSequence(array1, path_direction, i - 1, j, print_fun);
} else {
PrintSequence(array1, path_direction, i, j - 1, print_fun);
}
}
template<typename T>
void LongestCommonSubsequence(std::vector<T>& array1, const std::vector<T>&array2) {
boost::scoped_ptr<size_t> subsequence_length_buffer(new size_t[(array1.size() + 1) * (array2.size() + 1)]);
DualArray<size_t> subsequence_length(subsequence_length_buffer.get(), array2.size() + 1);
boost::scoped_ptr<T> path_direction_buffer(new char[(array1.size() + 1) * (array2.size() + 1)]);
DualArray<char> path_direction(path_direction_buffer.get(), array2.size() + 1 );
for (size_t i = 0; i <= array1.size(); ++i) {
subsequence_length[i][0] = 0;
}
for (size_t j = 0; j <= array2.size(); ++j) {
subsequence_length[0][j] = 0;
}

for (size_t i = 1; i <= array1.size(); ++i) {
for (size_t j = 1; j <= array2.size(); ++j) {
if (array1[i - 1] == array2[j - 1]) {
subsequence_length[i][j] = subsequence_length[i - 1][j - 1] + 1;
path_direction[i][j] = 'S';
} else if (subsequence_length[i - 1][j] >= subsequence_length[i][j - 1]) {
subsequence_length[i][j] = subsequence_length[i - 1][j];
path_direction[i][j] = 'U';
} else {
subsequence_length[i][j] = subsequence_length[i][j - 1];
path_direction[i][j] = 'L';
}
}
}
for (int i = 0; i <= array1.size(); ++i) {
for(int j = 0; j <= array2.size(); ++j) {
printf("%zd ", subsequence_length[i][j]);
}
printf("\n");
}
PrintSequence(array1, path_direction, array1.size(), array2.size(),Print);
printf("\n");
}
class Test{
};
int main(int argc, char** argv) {
char array1[] = {'B', 'D', 'C', 'A', 'B', 'A'};
std::vector<char> array_vector1(array1, array1 + sizeof(array1) / sizeof(char));
char array2[] = {'A', 'B', 'C', 'B', 'D', 'A', 'B'};
std::vector<char> array_vector2(array2, array2 + sizeof(array2) / sizeof(char));
LongestCommonSubsequence<char>(array_vector2, array_vector1);
}


关键是下标的处理问题,容易出现错误的几点是:

1)保存矩阵的行列数量要计算清楚,矩阵多出1行和1列用于存储初始值,这样初始时i-1和j-1的位置不会溢出

2)由于矩阵的下标从1开始,而传入的向量下标从0开始,因此访问向量时下标要-1,对于Print函数也是如此

3)注意DualArray的常量成员函数实现,为了满足常量参数调用的需要,内部需要转型操作

4)Print的实现允许用户定义的访问函数,通过函数模板参数实现
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: