zoukankan      html  css  js  c++  java
  • Leetcode | Distinct Subsequences

    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.

    题意有点歧义。其实是要求S中有多少个不同的子串等于T。

    dfs的思路很好写,就是从s查到*t,如果找到了,再从s+1中去找*(t+1),直到最后t为空。

     1 class Solution {
     2 public:
     3     int numDistinct(string S, string T) {
     4         count = 0;
     5         dfs(S.c_str(), T.c_str());
     6         return count;
     7     }
     8     
     9     void dfs(const char* s, const char* t) {
    10         if (*s == '') return;
    11         if (*t == '') {
    12             count++;
    13             return;
    14         }
    15         const char* p = s-1;
    16         while ((p = strchr(p+1, *t)) != NULL) {
    17             dfs(p, t+1);
    18         }
    19     }
    20 private:
    21     int count;
    22 };

    dfs对大数据会超时。仔细分析一下,分发现其实有许多重复计算。比如s="ccaaa", t="ca"。计算第一个c之后,会dfs到后面3个a的情况。然后回溯到第二个c的时候,又会再dfs到后面3个a。于是可以用dp来做。

    用nums[i][j]表示t[i...t.length-1]和s[j...s.length-1]有多少个Distinct Subsequences。我们最终求解就是nums[0][0]。

    1. 如果t[i] = s[j],那么nums[i][j]应该等于t[i...t.length-1]和s[j+1...s.length-1]的数目,还要加上前一个字符累计的数目,也就是t[i+1...t.length-1]和s[j+1...s.length-1]的数目。比如t="ca", s="ccaaa"。nums[0][1]=3,t[0]=s[0],那么nums[0][0]应该就等于"ca"和“caaa”的数目(nums[0][1]),加上“a"和”caaa“之间的数目(nums[1[1]),所以nums[0][0]=nums[0][1]+nums[1][1]=3+3=6;

    2. 如果t[i]!=s[j],那么nums[i][j]应该等于t[i...t.length-1]和s[j+1...s.length-1]的数目。比如t="ca", s="ccaaa", t[0]!=s[2],那么nums[0][2]应该等于"ca"和”aa"的数目,nums[0][2]=nums[0][3]=0。

    3. 关于初始值:

    nums[t.length][j...s.length]也就是t为空时,s[j...s.length]的数目,初始值应该为1,应该s[j...s.length]中有一个子串是空串。其他初始值都为0.

    比如t="ca", s="ccaaa"。nums[1][3]=nums[1][4]+nums[2][4]=(nums[1][5]+nums[2][5])+nums[2][4]=(0+1)+1=2.

     1 class Solution {
     2 public:
     3     int numDistinct(string S, string T) {
     4         if (T.empty()) return 0;
     5         if (S.empty()) return 0;
     6         int n1 = S.length();
     7         int n2 = T.length();
     8         vector<vector<int> > nums(n2 + 1, vector<int>(n1 + 1, 0));
     9         for (int i = 0; i <= n1; ++i) {
    10             nums[n2][i] = 1;
    11         }
    12         for (int i = n2 - 1; i >= 0; --i) {
    13             for (int j = n1 - 1; j >= 0; --j) {
    14                 if (T[i] == S[j]) {
    15                     nums[i][j] = nums[i][j + 1] + nums[i + 1][j + 1];
    16                 } else {
    17                     nums[i][j] = nums[i][j + 1];
    18                 }
    19             }
    20         }
    21         
    22         return nums[0][0];
    23     }
    24 };

     用一个滑动数组来优化一下,空间复杂度就是O(n),n是T的长度。

     1 class Solution {
     2 public:
     3     int numDistinct(string S, string T) {
     4         if (S.empty() || T.empty()) return 0;
     5         int n1 = S.length(), n2 = T.length();
     6         vector<vector<int> > dp(2, vector<int>(n2 + 1, 0));
     7         int cur = 0, next = 1;
     8         for (int i = n1 - 1; i >= 0; --i) {
     9             dp[cur][n2] = 1;
    10             for (int j = n2 - 1; j >= 0; --j) {
    11                 if (S[i] == T[j]) dp[next][j] = dp[cur][j + 1] + dp[cur][j];
    12                 else dp[next][j] = dp[cur][j];
    13             }
    14             cur = !cur; next = !next;
    15         }
    16         return dp[cur][0];
    17     }
    18 };
  • 相关阅读:
    不务正业系列-浅谈《过气堡垒》,一个RTS玩家的视角
    [LeetCode] 54. Spiral Matrix
    [LeetCode] 40. Combination Sum II
    138. Copy List with Random Pointer
    310. Minimum Height Trees
    4. Median of Two Sorted Arrays
    153. Find Minimum in Rotated Sorted Array
    33. Search in Rotated Sorted Array
    35. Search Insert Position
    278. First Bad Version
  • 原文地址:https://www.cnblogs.com/linyx/p/3720591.html
Copyright © 2011-2022 走看看