|
53 | 53 |
|
54 | 54 | <!-- 这里可写通用的实现逻辑 -->
|
55 | 55 |
|
| 56 | +**方法一:记忆化搜索** |
| 57 | + |
| 58 | +我们设计一个函数 $dfs(i, l, e, t)$,表示当前剩余字符串长度为 $i$,且已至少有 $l$ 个字符 `'l'`, $e$ 个字符 `'e'` 和 $t$ 个字符 `'t'`,构成的字符串是一个好字符串的方案数。那么答案为 $dfs(n, 0, 0, 0)$。 |
| 59 | + |
| 60 | +函数 $dfs(i, l, e, t)$ 的执行逻辑如下: |
| 61 | + |
| 62 | +如果 $i = 0$,说明当前字符串已经构造完毕,如果 $l = 1$, $e = 2$ 且 $t = 1$,说明当前字符串是一个好字符串,返回 $1$,否则返回 $0$。 |
| 63 | + |
| 64 | +否则,我们可以考虑在当前位置添加除 `'l'`, `'e'`, `'t'` 以外的任意一个小写字母,一共有 $23$ 种,那么此时得到的方案数为 $dfs(i - 1, l, e, t) \times 23$。 |
| 65 | + |
| 66 | +我们也可以考虑在当前位置添加 `'l'`,此时得到的方案数为 $dfs(i - 1, \min(1, l + 1), e, t)$。同理,添加 `'e'` 和 `'t'` 的方案数分别为 $dfs(i - 1, l, \min(2, e + 1), t)$ 和 $dfs(i - 1, l, e, \min(1, t + 1))$。累加起来,并对 $10^9 + 7$ 取模,即可得到 $dfs(i, l, e, t)$ 的值。 |
| 67 | + |
| 68 | +为了避免重复计算,我们可以使用记忆化搜索。 |
| 69 | + |
| 70 | +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为字符串长度。 |
| 71 | + |
| 72 | +**方法二:逆向思维 + 容斥原理** |
| 73 | + |
| 74 | +我们可以考虑逆向思维,即计算不包含子字符串 `"leet"` 的字符串数目,然后用总数减去该数目即可。 |
| 75 | + |
| 76 | +我们分成以下几种情况: |
| 77 | + |
| 78 | +- 情况 $a$:表示字符串中不包含字符 `'l'` 的方案数,那么有 $a = 25^n$。 |
| 79 | +- 情况 $b$:与 $a$ 类似,表示字符串中不包含字符 `'t'` 的方案数,那么有 $b = 25^n$。 |
| 80 | +- 情况 $c$:表示字符串中不包含字符 `'e'` 或者只包含一个字符 `'e'` 的方案数,那么有 $c = 25^n + n \times 25^{n - 1}$。 |
| 81 | +- 情况 $ab$:表示字符串中不包含字符 `'l'` 和 `'t'` 的方案数,那么有 $ab = 24^n$。 |
| 82 | +- 情况 $ac$:表示字符串中不包含字符 `'l'` 和 `'e'` 或者只包含一个字符 `'e'` 的方案数,那么有 $ac = 24^n + n \times 24^{n - 1}$。 |
| 83 | +- 情况 $bc$:与 $ac$ 类似,表示字符串中不包含字符 `'t'` 和 `'e'` 或者只包含一个字符 `'e'` 的方案数,那么有 $bc = 24^n + n \times 24^{n - 1}$。 |
| 84 | +- 情况 $abc$:表示字符串中不包含字符 `'l'`、`'t'` 和 `'e'` 或者只包含一个字符 `'e'` 的方案数,那么有 $abc = 23^n + n \times 23^{n - 1}$。 |
| 85 | + |
| 86 | +那么根据容斥原理,可以得到 $a + b + c - ab - ac - bc + abc$,就是不包含子字符串 `"leet"` 的字符串数目。 |
| 87 | + |
| 88 | +而总数 $tot = 26^n$,所以答案为 $tot - (a + b + c - ab - ac - bc + abc)$,注意要对 $10^9 + 7$ 取模。 |
| 89 | + |
| 90 | +时间复杂度 $O(\log n)$,其中 $n$ 为字符串长度。空间复杂度 $O(1)$。 |
| 91 | + |
56 | 92 | <!-- tabs:start -->
|
57 | 93 |
|
58 | 94 | ### **Python3**
|
59 | 95 |
|
60 | 96 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
61 | 97 |
|
62 | 98 | ```python
|
| 99 | +class Solution: |
| 100 | + def stringCount(self, n: int) -> int: |
| 101 | + @cache |
| 102 | + def dfs(i: int, l: int, e: int, t: int) -> int: |
| 103 | + if i == 0: |
| 104 | + return int(l == 1 and e == 2 and t == 1) |
| 105 | + a = dfs(i - 1, l, e, t) * 23 % mod |
| 106 | + b = dfs(i - 1, min(1, l + 1), e, t) |
| 107 | + c = dfs(i - 1, l, min(2, e + 1), t) |
| 108 | + d = dfs(i - 1, l, e, min(1, t + 1)) |
| 109 | + return (a + b + c + d) % mod |
| 110 | + |
| 111 | + mod = 10**9 + 7 |
| 112 | + return dfs(n, 0, 0, 0) |
| 113 | +``` |
63 | 114 |
|
| 115 | +```python |
| 116 | +class Solution: |
| 117 | + def stringCount(self, n: int) -> int: |
| 118 | + mod = 10**9 + 7 |
| 119 | + a = b = pow(25, n, mod) |
| 120 | + c = pow(25, n, mod) + n * pow(25, n - 1, mod) |
| 121 | + ab = pow(24, n, mod) |
| 122 | + ac = bc = (pow(24, n, mod) + n * pow(24, n - 1, mod)) % mod |
| 123 | + abc = (pow(23, n, mod) + n * pow(23, n - 1, mod)) % mod |
| 124 | + tot = pow(26, n, mod) |
| 125 | + return (tot - (a + b + c - ab - ac - bc + abc)) % mod |
64 | 126 | ```
|
65 | 127 |
|
66 | 128 | ### **Java**
|
67 | 129 |
|
68 | 130 | <!-- 这里可写当前语言的特殊实现逻辑 -->
|
69 | 131 |
|
70 | 132 | ```java
|
| 133 | +class Solution { |
| 134 | + private final int mod = (int) 1e9 + 7; |
| 135 | + private Long[][][][] f; |
| 136 | + |
| 137 | + public int stringCount(int n) { |
| 138 | + f = new Long[n + 1][2][3][2]; |
| 139 | + return (int) dfs(n, 0, 0, 0); |
| 140 | + } |
| 141 | + |
| 142 | + private long dfs(int i, int l, int e, int t) { |
| 143 | + if (i == 0) { |
| 144 | + return l == 1 && e == 2 && t == 1 ? 1 : 0; |
| 145 | + } |
| 146 | + if (f[i][l][e][t] != null) { |
| 147 | + return f[i][l][e][t]; |
| 148 | + } |
| 149 | + long a = dfs(i - 1, l, e, t) * 23 % mod; |
| 150 | + long b = dfs(i - 1, Math.min(1, l + 1), e, t); |
| 151 | + long c = dfs(i - 1, l, Math.min(2, e + 1), t); |
| 152 | + long d = dfs(i - 1, l, e, Math.min(1, t + 1)); |
| 153 | + return f[i][l][e][t] = (a + b + c + d) % mod; |
| 154 | + } |
| 155 | +} |
| 156 | +``` |
71 | 157 |
|
| 158 | +```java |
| 159 | +class Solution { |
| 160 | + private final int mod = (int) 1e9 + 7; |
| 161 | + |
| 162 | + public int stringCount(int n) { |
| 163 | + long a = qpow(25, n); |
| 164 | + long b = a; |
| 165 | + long c = (qpow(25, n) + n * qpow(25, n - 1) % mod) % mod; |
| 166 | + long ab = qpow(24, n); |
| 167 | + long ac = (qpow(24, n) + n * qpow(24, n - 1) % mod) % mod; |
| 168 | + long bc = ac; |
| 169 | + long abc = (qpow(23, n) + n * qpow(23, n - 1) % mod) % mod; |
| 170 | + long tot = qpow(26, n); |
| 171 | + return (int) ((tot - (a + b + c - ab - ac - bc + abc)) % mod + mod) % mod; |
| 172 | + } |
| 173 | + |
| 174 | + private long qpow(long a, int n) { |
| 175 | + long ans = 1; |
| 176 | + for (; n > 0; n >>= 1) { |
| 177 | + if ((n & 1) == 1) { |
| 178 | + ans = ans * a % mod; |
| 179 | + } |
| 180 | + a = a * a % mod; |
| 181 | + } |
| 182 | + return ans; |
| 183 | + } |
| 184 | +} |
72 | 185 | ```
|
73 | 186 |
|
74 | 187 | ### **C++**
|
75 | 188 |
|
76 | 189 | ```cpp
|
| 190 | +class Solution { |
| 191 | +public: |
| 192 | + int stringCount(int n) { |
| 193 | + const int mod = 1e9 + 7; |
| 194 | + using ll = long long; |
| 195 | + ll f[n + 1][2][3][2]; |
| 196 | + memset(f, -1, sizeof(f)); |
| 197 | + function<ll(int, int, int, int)> dfs = [&](int i, int l, int e, int t) -> ll { |
| 198 | + if (i == 0) { |
| 199 | + return l == 1 && e == 2 && t == 1 ? 1 : 0; |
| 200 | + } |
| 201 | + if (f[i][l][e][t] != -1) { |
| 202 | + return f[i][l][e][t]; |
| 203 | + } |
| 204 | + ll a = dfs(i - 1, l, e, t) * 23 % mod; |
| 205 | + ll b = dfs(i - 1, min(1, l + 1), e, t) % mod; |
| 206 | + ll c = dfs(i - 1, l, min(2, e + 1), t) % mod; |
| 207 | + ll d = dfs(i - 1, l, e, min(1, t + 1)) % mod; |
| 208 | + return f[i][l][e][t] = (a + b + c + d) % mod; |
| 209 | + }; |
| 210 | + return dfs(n, 0, 0, 0); |
| 211 | + } |
| 212 | +}; |
| 213 | +``` |
77 | 214 |
|
| 215 | +```cpp |
| 216 | +class Solution { |
| 217 | +public: |
| 218 | + int stringCount(int n) { |
| 219 | + const int mod = 1e9 + 7; |
| 220 | + using ll = long long; |
| 221 | + auto qpow = [&](ll a, int n) { |
| 222 | + ll ans = 1; |
| 223 | + for (; n; n >>= 1) { |
| 224 | + if (n & 1) { |
| 225 | + ans = ans * a % mod; |
| 226 | + } |
| 227 | + a = a * a % mod; |
| 228 | + } |
| 229 | + return ans; |
| 230 | + }; |
| 231 | + ll a = qpow(25, n); |
| 232 | + ll b = a; |
| 233 | + ll c = (qpow(25, n) + n * qpow(25, n - 1) % mod) % mod; |
| 234 | + ll ab = qpow(24, n); |
| 235 | + ll ac = (qpow(24, n) + n * qpow(24, n - 1) % mod) % mod; |
| 236 | + ll bc = ac; |
| 237 | + ll abc = (qpow(23, n) + n * qpow(23, n - 1) % mod) % mod; |
| 238 | + ll tot = qpow(26, n); |
| 239 | + return ((tot - (a + b + c - ab - ac - bc + abc)) % mod + mod) % mod; |
| 240 | + } |
| 241 | +}; |
78 | 242 | ```
|
79 | 243 |
|
80 | 244 | ### **Go**
|
81 | 245 |
|
82 | 246 | ```go
|
| 247 | +func stringCount(n int) int { |
| 248 | + const mod int = 1e9 + 7 |
| 249 | + f := make([][2][3][2]int, n+1) |
| 250 | + for i := range f { |
| 251 | + for j := range f[i] { |
| 252 | + for k := range f[i][j] { |
| 253 | + for l := range f[i][j][k] { |
| 254 | + f[i][j][k][l] = -1 |
| 255 | + } |
| 256 | + } |
| 257 | + } |
| 258 | + } |
| 259 | + var dfs func(i, l, e, t int) int |
| 260 | + dfs = func(i, l, e, t int) int { |
| 261 | + if i == 0 { |
| 262 | + if l == 1 && e == 2 && t == 1 { |
| 263 | + return 1 |
| 264 | + } |
| 265 | + return 0 |
| 266 | + } |
| 267 | + if f[i][l][e][t] == -1 { |
| 268 | + a := dfs(i-1, l, e, t) * 23 % mod |
| 269 | + b := dfs(i-1, min(1, l+1), e, t) |
| 270 | + c := dfs(i-1, l, min(2, e+1), t) |
| 271 | + d := dfs(i-1, l, e, min(1, t+1)) |
| 272 | + f[i][l][e][t] = (a + b + c + d) % mod |
| 273 | + } |
| 274 | + return f[i][l][e][t] |
| 275 | + } |
| 276 | + return dfs(n, 0, 0, 0) |
| 277 | +} |
| 278 | +``` |
| 279 | + |
| 280 | +```go |
| 281 | +func stringCount(n int) int { |
| 282 | + const mod int = 1e9 + 7 |
| 283 | + qpow := func(a, n int) int { |
| 284 | + ans := 1 |
| 285 | + for ; n > 0; n >>= 1 { |
| 286 | + if n&1 == 1 { |
| 287 | + ans = ans * a % mod |
| 288 | + } |
| 289 | + a = a * a % mod |
| 290 | + } |
| 291 | + return ans |
| 292 | + } |
| 293 | + a := qpow(25, n) |
| 294 | + b := a |
| 295 | + c := qpow(25, n) + n*qpow(25, n-1) |
| 296 | + ab := qpow(24, n) |
| 297 | + ac := (qpow(24, n) + n*qpow(24, n-1)) % mod |
| 298 | + bc := ac |
| 299 | + abc := (qpow(23, n) + n*qpow(23, n-1)) % mod |
| 300 | + tot := qpow(26, n) |
| 301 | + return ((tot-(a+b+c-ab-ac-bc+abc))%mod + mod) % mod |
| 302 | +} |
| 303 | +``` |
| 304 | + |
| 305 | +### **TypeScript** |
| 306 | + |
| 307 | +```ts |
| 308 | +function stringCount(n: number): number { |
| 309 | + const mod = 10 ** 9 + 7; |
| 310 | + const f: number[][][][] = Array.from({ length: n + 1 }, () => |
| 311 | + Array.from({ length: 2 }, () => |
| 312 | + Array.from({ length: 3 }, () => Array.from({ length: 2 }, () => -1)), |
| 313 | + ), |
| 314 | + ); |
| 315 | + const dfs = (i: number, l: number, e: number, t: number): number => { |
| 316 | + if (i === 0) { |
| 317 | + return l === 1 && e === 2 && t === 1 ? 1 : 0; |
| 318 | + } |
| 319 | + if (f[i][l][e][t] !== -1) { |
| 320 | + return f[i][l][e][t]; |
| 321 | + } |
| 322 | + const a = (dfs(i - 1, l, e, t) * 23) % mod; |
| 323 | + const b = dfs(i - 1, Math.min(1, l + 1), e, t); |
| 324 | + const c = dfs(i - 1, l, Math.min(2, e + 1), t); |
| 325 | + const d = dfs(i - 1, l, e, Math.min(1, t + 1)); |
| 326 | + return (f[i][l][e][t] = (a + b + c + d) % mod); |
| 327 | + }; |
| 328 | + return dfs(n, 0, 0, 0); |
| 329 | +} |
| 330 | +``` |
83 | 331 |
|
| 332 | +```ts |
| 333 | +function stringCount(n: number): number { |
| 334 | + const mod = BigInt(10 ** 9 + 7); |
| 335 | + const qpow = (a: bigint, n: number): bigint => { |
| 336 | + let ans = 1n; |
| 337 | + for (; n; n >>>= 1) { |
| 338 | + if (n & 1) { |
| 339 | + ans = (ans * a) % mod; |
| 340 | + } |
| 341 | + a = (a * a) % mod; |
| 342 | + } |
| 343 | + return ans; |
| 344 | + }; |
| 345 | + const a = qpow(25n, n); |
| 346 | + const b = a; |
| 347 | + const c = (qpow(25n, n) + ((BigInt(n) * qpow(25n, n - 1)) % mod)) % mod; |
| 348 | + const ab = qpow(24n, n); |
| 349 | + const ac = (qpow(24n, n) + ((BigInt(n) * qpow(24n, n - 1)) % mod)) % mod; |
| 350 | + const bc = ac; |
| 351 | + const abc = (qpow(23n, n) + ((BigInt(n) * qpow(23n, n - 1)) % mod)) % mod; |
| 352 | + const tot = qpow(26n, n); |
| 353 | + return Number((((tot - (a + b + c - ab - ac - bc + abc)) % mod) + mod) % mod); |
| 354 | +} |
84 | 355 | ```
|
85 | 356 |
|
86 | 357 | ### **...**
|
|
0 commit comments