Problem Description
Given two strings s and t, return the number of distinct subsequences of s that equal t. A subsequence of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters.
Key Insights
- Use dynamic programming to build the solution by comparing characters of s and t.
- Define a 2D dp table where dp[i][j] represents the number of ways to form the first j characters of t using the first i characters of s.
- The recurrence relation:
- If s[i-1] equals t[j-1], then include both the cases of matching this character as well as skipping it: dp[i][j] = dp[i-1][j-1] + dp[i-1][j].
- If they do not match, then simply skip the current character of s: dp[i][j] = dp[i-1][j].
- Initialize dp[i][0] = 1 for all i since an empty t can always be formed.
- The final answer is dp[s.length][t.length].
Space and Time Complexity
Time Complexity: O(n * m), where n is the length of s and m is the length of t. Space Complexity: O(n * m), which can be optimized to O(m) with careful row reuse.
Solution
We use a dynamic programming approach with a 2D table. The table has dimensions (len(s) + 1) x (len(t) + 1). Each cell dp[i][j] stores the number of distinct subsequences from the first i characters of s that match the first j characters of t.
Steps:
- Initialize dp[i][0] = 1 for every i, because an empty t is a subsequence of any prefix of s.
- Iterate over each character of s (outer loop) and for each, iterate over t (inner loop).
- For every character in s, if it equals the current character in t, update dp[i][j] as the sum of the ways by using or skipping this character. Otherwise, carry over the previous count.
- Return dp[len(s)][len(t)] as the result.