Welcome to Subscribe On Youtube

115. Distinct Subsequences

Description

Given two strings s and t, return the number of distinct subsequences of s which equals t.

The test cases are generated so that the answer fits on a 32-bit signed integer.

 

Example 1:

Input: s = "rabbbit", t = "rabbit"
Output: 3
Explanation:
As shown below, there are 3 ways you can generate "rabbit" from s.
rabbbit
rabbbit
rabbbit

Example 2:

Input: s = "babgbag", t = "bag"
Output: 5
Explanation:
As shown below, there are 5 ways you can generate "bag" from s.
babgbag
babgbag
babgbag
babgbag
babgbag

 

Constraints:

  • 1 <= s.length, t.length <= 1000
  • s and t consist of English letters.

Solutions

Solution 1: Dynamic Programming

We define $f[i][j]$ as the number of schemes where the first $i$ characters of string $s$ form the first $j$ characters of string $t$. Initially, $f[i][0]=1$ for all $i \in [0,m]$.

When $i > 0$, we consider the calculation of $f[i][j]$:

  • When $s[i-1] \ne t[j-1]$, we cannot select $s[i-1]$, so $f[i][j]=f[i-1][j]$;
  • Otherwise, we can select $s[i-1]$, so $f[i][j]=f[i-1][j-1]$.

Therefore, we have the following state transition equation:

\[f[i][j]=\left\{ \begin{aligned} &f[i-1][j], &s[i-1] \ne t[j-1] \\ &f[i-1][j-1]+f[i-1][j], &s[i-1]=t[j-1] \end{aligned} \right.\]

The final answer is $f[m][n]$, where $m$ and $n$ are the lengths of strings $s$ and $t$ respectively.

The time complexity is $O(m \times n)$, and the space complexity is $O(m \times n)$.

We notice that the calculation of $f[i][j]$ is only related to $f[i-1][..]$. Therefore, we can optimize the first dimension, reducing the space complexity to $O(n)$.

Solution 2

This implementation uses dynamic programming. It traverses the relevant values and updates its state as each value is processed. After all required states have been considered, the maintained result is returned.

  • class Solution {
        public int numDistinct(String s, String t) {
            int n = t.length();
            int[] f = new int[n + 1];
            f[0] = 1;
            for (char a : s.toCharArray()) {
                for (int j = n; j > 0; --j) {
                    char b = t.charAt(j - 1);
                    if (a == b) {
                        f[j] += f[j - 1];
                    }
                }
            }
            return f[n];
        }
    }
    
    
    // Solution 2
    class Solution {
        public int numDistinct(String s, String t) {
            int n = t.length();
            int[] f = new int[n + 1];
            f[0] = 1;
            for (char a : s.toCharArray()) {
                for (int j = n; j > 0; --j) {
                    char b = t.charAt(j - 1);
                    if (a == b) {
                        f[j] += f[j - 1];
                    }
                }
            }
            return f[n];
        }
    }
    
    
  • class Solution {
    public:
        int numDistinct(string s, string t) {
            int n = t.size();
            unsigned long long f[n + 1];
            memset(f, 0, sizeof(f));
            f[0] = 1;
            for (char& a : s) {
                for (int j = n; j; --j) {
                    char b = t[j - 1];
                    if (a == b) {
                        f[j] += f[j - 1];
                    }
                }
            }
            return f[n];
        }
    };
    
    
    // Solution 2
    class Solution {
    public:
        int numDistinct(string s, string t) {
            int n = t.size();
            unsigned long long f[n + 1];
            memset(f, 0, sizeof(f));
            f[0] = 1;
            for (char& a : s) {
                for (int j = n; j; --j) {
                    char b = t[j - 1];
                    if (a == b) {
                        f[j] += f[j - 1];
                    }
                }
            }
            return f[n];
        }
    };
    
    
  • class Solution:
        def numDistinct(self, s: str, t: str) -> int:
            n = len(t)
            f = [1] + [0] * n
            for a in s:
                for j in range(n, 0, -1):
                    if a == t[j - 1]:
                        f[j] += f[j - 1]
            return f[n]
    
    
    # Solution 2
    class Solution:
        def numDistinct(self, s: str, t: str) -> int:
            n = len(t)
            f = [1] + [0] * n
            for a in s:
                for j in range(n, 0, -1):
                    if a == t[j - 1]:
                        f[j] += f[j - 1]
            return f[n]
    
    
  • func numDistinct(s string, t string) int {
    	n := len(t)
    	f := make([]int, n+1)
    	f[0] = 1
    	for _, a := range s {
    		for j := n; j > 0; j-- {
    			if b := t[j-1]; byte(a) == b {
    				f[j] += f[j-1]
    			}
    		}
    	}
    	return f[n]
    }
    
    
    // Solution 2
    func numDistinct(s string, t string) int {
    	n := len(t)
    	f := make([]int, n+1)
    	f[0] = 1
    	for _, a := range s {
    		for j := n; j > 0; j-- {
    			if b := t[j-1]; byte(a) == b {
    				f[j] += f[j-1]
    			}
    		}
    	}
    	return f[n]
    }
    
    
  • function numDistinct(s: string, t: string): number {
        const n = t.length;
        const f: number[] = new Array(n + 1).fill(0);
        f[0] = 1;
        for (const a of s) {
            for (let j = n; j; --j) {
                const b = t[j - 1];
                if (a === b) {
                    f[j] += f[j - 1];
                }
            }
        }
        return f[n];
    }
    
    
    // Solution 2
    function numDistinct(s: string, t: string): number {
        const n = t.length;
        const f: number[] = new Array(n + 1).fill(0);
        f[0] = 1;
        for (const a of s) {
            for (let j = n; j; --j) {
                const b = t[j - 1];
                if (a === b) {
                    f[j] += f[j - 1];
                }
            }
        }
        return f[n];
    }
    
    
  • impl Solution {
        #[allow(dead_code)]
        pub fn num_distinct(s: String, t: String) -> i32 {
            let n = s.len();
            let m = t.len();
            let mut dp: Vec<Vec<u64>> = vec![vec![0; m + 1]; n + 1];
    
            // Initialize the dp vector
            for i in 0..=n {
                dp[i][0] = 1;
            }
    
            // Begin the actual dp process
            for i in 1..=n {
                for j in 1..=m {
                    dp[i][j] = if s.as_bytes()[i - 1] == t.as_bytes()[j - 1] {
                        dp[i - 1][j] + dp[i - 1][j - 1]
                    } else {
                        dp[i - 1][j]
                    };
                }
            }
    
            dp[n][m] as i32
        }
    }
    
    
  • class Solution {
        public int numDistinct(String s, String t) {
            int n = t.length();
            int[] f = new int[n + 1];
            f[0] = 1;
            for (char a : s.toCharArray()) {
                for (int j = n; j > 0; --j) {
                    char b = t.charAt(j - 1);
                    if (a == b) {
                        f[j] += f[j - 1];
                    }
                }
            }
            return f[n];
        }
    }
    
  • class Solution {
    public:
        int numDistinct(string s, string t) {
            int n = t.size();
            unsigned long long f[n + 1];
            memset(f, 0, sizeof(f));
            f[0] = 1;
            for (char& a : s) {
                for (int j = n; j; --j) {
                    char b = t[j - 1];
                    if (a == b) {
                        f[j] += f[j - 1];
                    }
                }
            }
            return f[n];
        }
    };
    
  • class Solution:
        def numDistinct(self, s: str, t: str) -> int:
            n = len(t)
            f = [1] + [0] * n
            for a in s:
                for j in range(n, 0, -1):
                    if a == t[j - 1]:
                        f[j] += f[j - 1]
            return f[n]
    
    
  • func numDistinct(s string, t string) int {
    	n := len(t)
    	f := make([]int, n+1)
    	f[0] = 1
    	for _, a := range s {
    		for j := n; j > 0; j-- {
    			if b := t[j-1]; byte(a) == b {
    				f[j] += f[j-1]
    			}
    		}
    	}
    	return f[n]
    }
    
  • function numDistinct(s: string, t: string): number {
        const n = t.length;
        const f: number[] = new Array(n + 1).fill(0);
        f[0] = 1;
        for (const a of s) {
            for (let j = n; j; --j) {
                const b = t[j - 1];
                if (a === b) {
                    f[j] += f[j - 1];
                }
            }
        }
        return f[n];
    }
    
    

All Problems

All Solutions