Categorygithub.com/szhou12/leetcode-goleetcode2930-Number-of-Strings-Which-Can-Be-Rearranged-to-Contain-Substring
package
0.0.0-20241220224003-b7cf03a90b2b
Repository: https://github.com/szhou12/leetcode-go.git
Documentation: pkg.go.dev
# README
2930. Number of Strings Which Can Be Rearranged to Contain Substring
Solution idea
1. DP
Key Idea: 大多数数学中的组合问题都是通过 DP 来推导得到的
- 组合公式:
C(n, m) = C(n-1, m) + C(n-1, m-1)
- 转换成 DP 等价于:
dp[n][m] = dp[n-1][m] + dp[n-1][m-1]
- 数学意义:n中选m个, 要问的是: 第n个取不取?如果不取,就转化成从前n-1个中取m个;如果取,就转化成选定第n个,再从前n-1个中取m-1个
解题思路:在由 n 个字母组成的字符串中,挖掉4个位子放入 'l', 'e', 'e', 't' (order doesn't matter),有多少种组合的可能?
DP Solution
- Definition:
DP[i][a][b][c] =
number of strings of i letters that have at leasta
number of 'l',b
number of 'e',c
number of 't' wherea = 0, 1
,b = 0, 1, 2
,c = 0, 1
. - Base Case:
DP[0][0][0][0] = 1
满足条件的 (没有 'l', 'e', 't') 空串有且只有一个 - Recurrence: 应用公式
C(n, m) = C(n-1, m) + C(n-1, m-1)
DP[i][1][b][c] += DP[i-1][0][b][c]
如果第i个字母是 'l',且取第i个使DP[i]
包含至少1个'l' (a==1
)DP[i][a][1][c] += DP[i-1][a][0][c]
如果第i个字母是 'e',且取第i个使DP[i]
包含至少1个'e' (b==1
)DP[i][a][2][c] += DP[i-1][a][1][c]
如果第i个字母是 'e',且取第i个使DP[i]
包含至少2个'e' (b==2
)DP[i][a][b][1] += DP[i-1][a][b][0]
如果第i个字母是 't',且取第i个使DP[i]
包含至少1个't' (c==1
)DP[i][a][b][c] += DP[i-1][a][b][c]
所有其他的情况, 不取第i个 ==C(n-1, m)
Time Complexity = $O(2\times 3\times 2\times 26\times n) = O(n)$
2. Math: PIE (inclusion-exclusion)
$A =$ the string has $\leq 1$ 'e'
$B =$ the string has no 'l'
$C =$ the string has no 't'
$|A\cup B\cup C| =$ the number of strings that have <= 1 'e' or no 'l' or no 't' = the total number of BAD strings
By PIE (inclusion-exclusion), $|A\cup B\cup C| = |A| + |B| + |C| - (|A\cap B|+|A\cap C|+|B\cap C|) + |A\cap B \cap C|$
$|A| = n\cdot 25^{n-1} + 25^n$
- no 'e': $25^n$
- exactly one 'e': ${n \choose 1} \cdot 25^{n-1}$ (选一个位子放'e',其余位子放除了'e'任意字母)
$|B| = 25^n$
$|C| = 25^n$
$|B\cap C| = 24^n$
$|A\cap B| = n\cdot 24^{n-1} + 24^n$
- no 'e' + no 'l': $24^n$
- exactly one 'e' + no 'l': ${n \choose 1} \cdot 24^{n-1}$ (选一个位子放'e',其余位子放除了'e'和'l'任意字母)
$|A\cap C| = n\cdot 24^{n-1} + 24^n$
- no 'e' + no 't': $24^n$
- exactly one 'e' + no 't': ${n \choose 1} \cdot 24^{n-1}$ (选一个位子放'e',其余位子放除了'e'和't'任意字母)
$|A\cap B\cap C| = n\cdot 23^{n-1} + 23^n$
- no 'e' + no 'l' + no 't': $23^n$
- exactly one 'e' + no 'l' + no 't': ${n \choose 1} \cdot 23^{n-1}$ (选一个位子放'e',其余位子放除了'e'、'l'、't'任意字母)
Good strings = Total strings - Bad strings = $26^n - |A\cup B\cup C|$
- :exclamation: 编者注:
- 我也有尝试推导本题的数学表达式,得出的是: $C(n, 4) \times \frac{P(4,4)}{P(2,2)} \times 26^{n-4} = C(n, 4) \times 12 \times 26^{n-4}$
- 即, 从n个中挑出4个位子放入 'l', 'e', 'e', 't'进行排列,其余位子可以放入任意26个字母中的一个
- 但是!这个表达式会导致重复计算。例如: n=5时, 表达式得到 1560,而 DP 得到 1460。当 n > 4时,表达式的结果总会大于 DP 的结果
- 网上的参考答案从逆向角度来解题,使用 PIE (inclusion-exclusion),虽然繁琐,但可以避免重复计算