Distinct Subsequences
HardThe problem
A subsequence keeps some characters of a string in order, possibly skipping some. Return how many different ways you can pick characters of s (by position) that spell t exactly.
- Example 1Input: s = "rabbbit", t = "rabbit"Output: 3
You can skip any one of the three "b" characters in s.
- Example 2Input: s = "babgbag", t = "bag"Output: 5
There are 5 different sets of positions in s that spell "bag".
Limits
- 1 ≤ len(s), len(t) ≤ 1,000
- Both strings have only English letters
- The answer fits in a 32-bit integer
Write it in Go. Try for about 20 minutes on paper first, then open one hint at a time.
Try it here
Write Go. Common packages like fmt and sort are imported for you. Keep the function name and inputs the same.
Hints, one at a time
Nudge
When the characters match you may use the match or skip the character in s.
The idea
dp[i][j] = dp[i−1][j] (skip s[i−1]) + (s[i−1]==t[j−1] ? dp[i−1][j−1] : 0); dp[i][0] = 1.
Target: O(m·n) time
Go function shape
func numDistinct(s string, t string) intReference solution
Tested with go test. Try it yourself first, then compare.
// NumDistinct: how many ways does t appear as a subsequence of s?
// dp[j] = ways to build the first j letters of t from the part of s seen so far.
func NumDistinct(s, t string) int {
dp := make([]int, len(t)+1)
dp[0] = 1
for i := 0; i < len(s); i++ {
for j := len(t); j >= 1; j-- { // descending so dp[j-1] still holds the previous row
if s[i] == t[j-1] {
dp[j] += dp[j-1]
}
}
}
return dp[len(t)]
}