This question is part of my Career Advice series.
Original question: https://neetcode.io/problems/count-subsequences
The task is to determine the number of distinct subsequences of string s
that are equal to string t
. A subsequence is a sequence derived from another sequence by deleting some or no elements without changing the order of the remaining elements.
Clarifying Questions:
s
relative to t
? (In this problem, s
can be longer than t
, but if t
is longer than s
, there are no valid subsequences).dp[i][j]
represents the number of distinct subsequences of s[0...i-1]
that equal t[0...j-1]
.s
when matching with t
.dp[i][0]
should be 1 for all i
because an empty string t
can always be formed by any string s
by deleting all characters.s
, decide whether to match it with the current character in t
or skip it.function numDistinct(s, t) {
const m = s.length;
const n = t.length;
// DP table where dp[i][j] means number of subsequences in s[0..i-1] that match t[0..j-1]
const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
// Base case: An empty t can always be matched by any prefix of s by removing all characters
for (let i = 0; i <= m; i++) {
dp[i][0] = 1;
}
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
if (s[i - 1] === t[j - 1]) {
// If characters match, count subsequences including and excluding current char
dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
} else {
// Otherwise, carry forward the count without including current char of s
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[m][n];
}
dp
is initialized such that dp[i][0]
is 1, indicating that any prefix of s
can match an empty t
.s
and t
match (s[i-1] == t[j-1]
), then we add the number of subsequences where:
s
in our match (dp[i-1][j-1]
).s
and just carry forward the previous count (dp[i-1][j]
).s
.dp[m][n]
gives the total number of distinct subsequences of s
that match t
.