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

程序代码如下:

#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的实现允许用户定义的访问函数,通过函数模板参数实现

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值