Question

Formatted question description: https://leetcode.ca/all/115.html

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.

Algorithm

	r a b b b i t
	1 1 1 1 1 1 1 1
r 0 1 1 1 1 1 1 1
a 0 0 1 1 1 1 1 1
b 0 0 0 1 2 3 3 3
b 0 0 0 0 1 3 3 3
i 0 0 0 0 0 0 3 3
t 0 0 0 0 0 0 0 3

dp[0][0] = 1; // T and S are both empty strings. dp[0][1 … S.length()-1] = 1; // T is an empty string, S has only one subsequence match. dp[1 … T.length()-1][0] = 0; // S is an empty string, T is not an empty string, and S has no subsequence matching. dp[i][j] = dp[i][j-1] + (T[i-1] == S[j-1]? dp[i-1][j-1]: 0)

Code

Java

  • 
    public class Distinct_Subsequences {
    
    	public class Solution_iteration {
    	    public int numDistinct(String s, String t) {
    
    	        if (s == null || t == null)     return 0;
    	        if (s.length() < t.length())    return 0;
    
    	        int TLength = t.length();
    	        int SLength = s.length();
    
    	        int[][] dp = new int[TLength + 1][SLength + 1];
    	        dp[0][0] = 1;
    
    	        for (int i = 1; i <= SLength; i++) {
    	            dp[0][i] = 1;
    	        }
    	        for (int i = 1; i <= TLength; i++) {
    	            dp[i][0] = 0;
    	        }
    
    	        for (int i = 1; i <= TLength; i++) {
    	            for (int j = 1; j <= SLength; j++) {
    	                if (t.charAt(i - 1) == s.charAt(j - 1)) {
    	                    dp[i][j] = dp[i][j - 1] + dp[i - 1][j - 1];
    	                } else {
    	                    dp[i][j] = dp[i][j - 1];
    	                }
    	            }
    	        }
    
    	        return dp[TLength][SLength];
    	    }
    	}
    
    	/*
    	Last executed input:
    	"aabdbaabeeadcbbdedacbbeecbabebaeeecaeabaedadcbdbcdaabebdadbbaeabdadeaabbabbecebbebcaddaacccebeaeedababedeacdeaaaeeaecbe"
    	"bddabdcae"
    	*/
    	public class Solution_recursion {
    	    public int numDistinct(String s, String t) {
    
    	        if (s.length() == 0) {
    	            return t.length() == 0 ? 1 : 0;
    	        }
    
    	        if (t.length() == 0) {
    	            return s.length() >= 0 ? 1 : 0; // @note: t is empty, so delete all in s is one solution
    	        }
    
    	        if (s.length() < t.length()) {
    	            return 0;
    	        }
    
    	        int sum = 0;
    
    	        if (s.charAt(0) == t.charAt(0)) {
    	            sum += numDistinct(s.substring(1), t.substring(1));
    	        }
    
    	        sum += numDistinct(s.substring(1), t); // @note: anyway, have to try this one: eg, s='aa' and t='a', result=2
    
    	        return sum;
    
    	    }
    	}
    
    }
    
  • // OJ: https://leetcode.com/problems/distinct-subsequences
    // Time: O(MN)
    // Space: O(N)
    class Solution {
    public:
        int numDistinct(string s, string t) {
            int M = s.size(), N = t.size();
            vector<long> dp(N + 1);
            dp[0] = 1;
            for (int i = 0; i < M; ++i) {
                for (int j = N - 1; j >= 0; --j) {
                    if (s[i] == t[j]) dp[j + 1] += dp[j];
                    if (dp[j + 1] > INT_MAX) dp[j + 1] = 0;
                }
            }
            return dp[N];
        }
    };
    
  • class Solution(object):
      # space O(n^2)
      def _numDistinct(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: int
        """
        dp = [[0] * (len(t) + 1) for _ in range(0, len(s) + 1)]
    
        for i in range(0, len(s) + 1):
          dp[i][0] = 1
    
        for i in range(1, len(s) + 1):
          for j in range(1, len(t) + 1):
            dp[i][j] += dp[i - 1][j]
            if t[j - 1] == s[i - 1]:
              dp[i][j] += dp[i - 1][j - 1]
    
        return dp[-1][-1]
    
      def numDistinct(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: int
        """
        dp = [0] * (len(t) + 1)
        for i in range(1, len(s) + 1):
          pre = 1
          for j in range(1, len(t) + 1):
            tmp = dp[j]
            if t[j - 1] == s[i - 1]:
              dp[j] += pre
            pre = tmp
        return dp[-1]
    
    

All Problems

All Solutions