• LeetCode


    Distinct Subsequences

    2014.2.8 22:11

    Given a string S and a string T, count the number of distinct subsequences of T in S.

    A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE" is a subsequence of "ABCDE" while "AEC" is not).

    Here is an example:
    S = "rabbbit"T = "rabbit"

    Return 3.

    Solution1:

      The first solution I think of is by recursive searching. After counting the occurrence of every alphabet and recording the indices, we can solve the problem by a recursive search, which ends when the total string T is matched.

      After testing the code myself, it ran well under small scale, but slowed down in front of long strings, exactly as I expected.

      If we're to find out a more efficient solution, dynamic programming would be a better strategy:

        1. Let dp[x][y] be the number of possible combinations of T[1:y] in S[1:x].

        2. dp[x][0] = 0.

        3. dp[0][y] = 0.

        4. if S[x] = T[1], dp[x][1] = dp[x - 1][1] + 1, else dp[x][1] = dp[x - 1][1].

        5. if S[x] = T[y], dp[x][y] = dp[x - 1][y] + dp[x - 1][y - 1], else dp[x][y] = dp[x - 1][y].

      The dynamic programming is O(n^2) scale.

      Time and space complexities are both O(len(S) * len(T)).

    Accepted code:

     1 // 2RE, 1WA, 1AC, don't use memset on dp[][], although it looks as if it were one block of memory.
     2 #include <cstring>
     3 #include <vector>
     4 using namespace std;
     5 
     6 class Solution {
     7 public:
     8     int numDistinct(string S, string T) {
     9         int **dp;
    10         int ls, lt;
    11         int result;
    12         int i, j;
    13         
    14         ls = (int)S.size();
    15         lt = (int)T.size();
    16         if (ls == 0 || lt == 0) {
    17             return 0;
    18         }
    19         
    20         dp = new int*[ls + 1];
    21         for (i = 0; i < ls + 1; ++i) {
    22             dp[i] = new int[lt + 1];
    23         }
    24         for (i = 0; i <= ls; ++i) {
    25             for (j = 0; j <= lt; ++j) {
    26                 dp[i][j] = 0;
    27             }
    28         }
    29         /*
    30         for (i = 0; i <= ls; ++i) {
    31             dp[i][0] = 0;
    32         }
    33         for (i = 0; i <= lt; ++i) {
    34             dp[0][i] = 0;
    35         }
    36         */
    37         for (i = 1; i <= ls; ++i) {
    38             if (S[i - 1] == T[0]) {
    39                 dp[i][1] = dp[i - 1][1] + 1;
    40             } else {
    41                 dp[i][1] = dp[i - 1][1];
    42             }
    43         }
    44         
    45         for (i = 2; i <= ls; ++i) {
    46             for (j = 2; j <= lt; ++j) {
    47                 if (S[i - 1] == T[j - 1]) {
    48                     dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1];
    49                 } else {
    50                     dp[i][j] = dp[i - 1][j];
    51                 }
    52             }
    53         }
    54         result = dp[ls][lt];
    55         for (i = 0; i < ls + 1; ++i) {
    56             delete[] dp[i];
    57         }
    58         delete[] dp;
    59         dp = NULL;
    60         
    61         return result;
    62     }
    63 };

     Solution2:

      The dynamic programming version can be optimized to linear space complexity, using only two rows, switching alternatively.

      Time complexity is O(len(S) * len(T)). Space complexity is O(len(T)).

    Accepted code:

     1 // 2RE, 1WA, 1AC, don't use memset on dp[][], although it looks as if it were one block of memory.
     2 #include <cstring>
     3 #include <vector>
     4 using namespace std;
     5 
     6 class Solution {
     7 public:
     8     int numDistinct(string S, string T) {
     9         int **dp;
    10         int ls, lt;
    11         int result;
    12         int i, j;
    13         
    14         ls = (int)S.size();
    15         lt = (int)T.size();
    16         if (ls == 0 || lt == 0 || ls < lt) {
    17             return 0;
    18         }
    19         
    20         dp = new int*[2];
    21         for (i = 0; i < 2; ++i) {
    22             dp[i] = new int[lt + 1];
    23         }
    24         for (i = 0; i < 2; ++i) {
    25             for (j = 0; j <= lt; ++j) {
    26                 dp[i][j] = 0;
    27             }
    28         }
    29         
    30         if (S[0] == T[0]) {
    31             dp[1][1] = 1;
    32         }
    33         
    34         int flag;
    35         flag = 0;
    36         for (i = 2; i <= ls; ++i) {
    37             dp[flag][0] = 0;
    38             if (S[i - 1] == T[0]) {
    39                 dp[flag][1] = dp[!flag][1] + 1;
    40             } else {
    41                 dp[flag][1] = dp[!flag][1];
    42             }
    43             for (j = 2; j <= lt; ++j) {
    44                 if (S[i - 1] == T[j - 1]) {
    45                     dp[flag][j] = dp[!flag][j] + dp[!flag][j - 1];
    46                 } else {
    47                     dp[flag][j] = dp[!flag][j];
    48                 }
    49             }
    50             flag = !flag;
    51         }
    52         flag = !flag;
    53         result = dp[flag][lt];
    54         for (i = 0; i < 2; ++i) {
    55             delete[] dp[i];
    56         }
    57         delete[] dp;
    58         dp = NULL;
    59         
    60         return result;
    61     }
    62 };
  • 相关阅读:
    VMware Workstation 6.0 正式版公布
    KMyMoney:全体理财好管家
    Bugzilla 3.0 公布
    Brightside:切换工作区的小东西
    QTM-Blogging 客户端
    MDF2ISO-将 MDF 转换为 ISO
    Yakuake 2.8 beta1
    Red Hat 的 Liberation 字体
    Dictman:有效的词典呆板人
    digiKam 0.9.2 Beta 1
  • 原文地址:https://www.cnblogs.com/zhuli19901106/p/3541108.html
Copyright © 2020-2023  润新知