Distinct Subsequences

题目: 给定两个string \(S\)\(T\),计算序列为\(T\)\(S\)的子序列的数量。

例如S = "rabbbit", T = "rabbit",返回结果为3
子序列:例如,"ACE"是"ABCDE"的子序列。

这里我用动态规划的来求解

  • 构建DP表,大小为 \(T.size + 1\)行,\(S.size + 1\)
    +1是为了后面查表方便。
  • 第一次,填表:判断T[j] 是否 等于 S[i] 。1代表相同,0代表不同
  • 第二次,查表:从T[1]到T[end] 有几种走法
    走法:从1到1,走也是有条件的,只能走自己的斜下方的方向,不能垂直向下,向右走
    有几种走法即有几个子序列
    计算有几种走法可以用递归,但效率较低,可用循环。
![](//images0.cnblogs.com/blog/661985/201502/152113244487788.png)

代码中的查表为从后向前

下面为C++代码

int numDistinct(string S, string T) {
   int num_T = T.size(), num_S = S.size();
   if (num_S < num_T) return 0;

   vector<vector<int>>  DP(num_T + 1, vector<int>(num_S + 1, 0)); //初始化DP表,全为0
   for (int i = 0; i < num_S; ++i){   // DP表第一行为1,最后一个为0
      DP[0][i] = 1;
   }
   // DP 填表
   for (int j = 1; j < num_T + 1; ++j){
      for (int i = j; i < num_S + 1; ++i){
         if (T[j - 1] == S[i - 1]){
            DP[j][i] = 1; 
         }
      }
   }
   // 查表,计算得到结果
   for (int j = num_T; j > 0; --j){
      int nn = 0;
      for (int i = num_S - (num_T - j); i > 0; --i){ 
         nn += DP[j][i];
         if (DP[j - 1][i - 1] >= 1){
            DP[j - 1][i - 1] = nn;
         }
      }
   }
   return DP[0][0];
}

时间复杂度 \(O(n*m)\)

空间\(O(n*m)\)

posted @ 2015-02-15 19:13  clq.lib  阅读(159)  评论(0编辑  收藏  举报