@@ -79,32 +79,211 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3320.Co
79
79
80
80
<!-- solution:start -->
81
81
82
- ### 方法一
82
+ ### 方法一:记忆化搜索
83
+
84
+ 我们设计一个函数 $\textit{dfs}(i, j, k)$,其中 $i$ 表示从字符串 $s$ 的第 $i$ 个字符开始,目前 $\textit{Alice}$ 与 $\textit{Bob}$ 的分数差为 $j$,并且 $\textit{Bob}$ 上一次召唤的生物是 $k$,一共有多少种 $\textit{Bob}$ 的出招序列可以战胜 $\textit{Alice}$。
85
+
86
+ 那么答案就是 $\textit{dfs}(0, 0, -1)$。其中 $-1$ 表示 $\textit{Bob}$ 还没有召唤过生物。在除了 $\textit{Python}$ 之外的语言中,由于分数差可能为负数,我们可以将分数差加上 $n$,这样就可以保证分数差为非负数。
87
+
88
+ 函数 $\textit{dfs}(i, j, k)$ 的计算过程如下:
89
+
90
+ - 如果 $n - i \leq j$,那么剩余的回合数不足以使 $\textit{Bob}$ 的分数超过 $\textit{Alice}$ 的分数,此时返回 $0$。
91
+ - 如果 $i \geq n$,那么所有回合已经结束,如果 $\textit{Bob}$ 的分数小于 $0$,那么返回 $1$,否则返回 $0$。
92
+ - 否则,我们枚举 $\textit{Bob}$ 这一回合召唤的生物,如果这一回合召唤的生物与上一回合召唤的生物相同,那么这一回合 $\textit{Bob}$ 无法获胜,直接跳过。否则,我们递归计算 $\textit{dfs}(i + 1, j + \textit{calc}(d[ s[ i]] , l), l)$,其中 $\textit{calc}(x, y)$ 表示 $x$ 与 $y$ 之间的胜负关系,而 $d$ 是一个映射,将字符映射到 $\textit{012}$。我们将所有的结果相加并对 $10^9 + 7$ 取模。
93
+
94
+ 时间复杂度 $O(n^2 \times k^2)$,其中 $n$ 是字符串 $s$ 的长度,而 $k$ 表示字符集的大小。空间复杂度 $O(n^2 \times k)$。
83
95
84
96
<!-- tabs:start -->
85
97
86
98
#### Python3
87
99
88
100
``` python
89
-
101
+ class Solution :
102
+ def countWinningSequences (self , s : str ) -> int :
103
+ def calc (x : int , y : int ) -> int :
104
+ if x == y:
105
+ return 0
106
+ if x < y:
107
+ return 1 if x == 0 and y == 2 else - 1
108
+ return - 1 if x == 2 and y == 0 else 1
109
+
110
+ @cache
111
+ def dfs (i : int , j : int , k : int ) -> int :
112
+ if len (s) - i <= j:
113
+ return 0
114
+ if i >= len (s):
115
+ return int (j < 0 )
116
+ res = 0
117
+ for l in range (3 ):
118
+ if l == k:
119
+ continue
120
+ res = (res + dfs(i + 1 , j + calc(d[s[i]], l), l)) % mod
121
+ return res
122
+
123
+ mod = 10 ** 9 + 7
124
+ d = {" F" : 0 , " W" : 1 , " E" : 2 }
125
+ ans = dfs(0 , 0 , - 1 )
126
+ dfs.cache_clear()
127
+ return ans
90
128
```
91
129
92
130
#### Java
93
131
94
132
``` java
95
-
133
+ class Solution {
134
+ private int n;
135
+ private char [] s;
136
+ private int [] d = new int [26 ];
137
+ private Integer [][][] f;
138
+ private final int mod = (int ) 1e9 + 7 ;
139
+
140
+ public int countWinningSequences (String s ) {
141
+ d[' W' - ' A' ] = 1 ;
142
+ d[' E' - ' A' ] = 2 ;
143
+ this . s = s. toCharArray();
144
+ n = this . s. length;
145
+ f = new Integer [n][n + n + 1 ][4 ];
146
+ return dfs(0 , n, 3 );
147
+ }
148
+
149
+ private int dfs (int i , int j , int k ) {
150
+ if (n - i <= j - n) {
151
+ return 0 ;
152
+ }
153
+ if (i >= n) {
154
+ return j - n < 0 ? 1 : 0 ;
155
+ }
156
+ if (f[i][j][k] != null ) {
157
+ return f[i][j][k];
158
+ }
159
+
160
+ int ans = 0 ;
161
+ for (int l = 0 ; l < 3 ; ++ l) {
162
+ if (l == k) {
163
+ continue ;
164
+ }
165
+ ans = (ans + dfs(i + 1 , j + calc(d[s[i] - ' A' ], l), l)) % mod;
166
+ }
167
+ return f[i][j][k] = ans;
168
+ }
169
+
170
+ private int calc (int x , int y ) {
171
+ if (x == y) {
172
+ return 0 ;
173
+ }
174
+ if (x < y) {
175
+ return x == 0 && y == 2 ? 1 : - 1 ;
176
+ }
177
+ return x == 2 && y == 0 ? - 1 : 1 ;
178
+ }
179
+ }
96
180
```
97
181
98
182
#### C++
99
183
100
184
``` cpp
101
-
185
+ class Solution {
186
+ public:
187
+ int countWinningSequences(string s) {
188
+ int n = s.size();
189
+ int d[ 26] {};
190
+ d[ 'W' - 'A'] = 1;
191
+ d[ 'E' - 'A'] = 2;
192
+ int f[ n] [ n + n + 1 ] [ 4] ;
193
+ memset(f, -1, sizeof(f));
194
+ auto calc = [ ] (int x, int y) -> int {
195
+ if (x == y) {
196
+ return 0;
197
+ }
198
+ if (x < y) {
199
+ return x == 0 && y == 2 ? 1 : -1;
200
+ }
201
+ return x == 2 && y == 0 ? -1 : 1;
202
+ };
203
+ const int mod = 1e9 + 7;
204
+ auto dfs = [ &] (auto&& dfs, int i, int j, int k) -> int {
205
+ if (n - i <= j - n) {
206
+ return 0;
207
+ }
208
+ if (i >= n) {
209
+ return j - n < 0 ? 1 : 0;
210
+ }
211
+ if (f[ i] [ j ] [ k] != -1) {
212
+ return f[ i] [ j ] [ k] ;
213
+ }
214
+ int ans = 0;
215
+ for (int l = 0; l < 3; ++l) {
216
+ if (l == k) {
217
+ continue;
218
+ }
219
+ ans = (ans + dfs(dfs, i + 1, j + calc(d[ s[ i] - 'A'] , l), l)) % mod;
220
+ }
221
+ return f[ i] [ j ] [ k] = ans;
222
+ };
223
+ return dfs(dfs, 0, n, 3);
224
+ }
225
+ };
102
226
```
103
227
104
228
#### Go
105
229
106
230
```go
107
-
231
+ func countWinningSequences(s string) int {
232
+ const mod int = 1e9 + 7
233
+ d := [26]int{}
234
+ d['W'-'A'] = 1
235
+ d['E'-'A'] = 2
236
+ n := len(s)
237
+ f := make([][][4]int, n)
238
+ for i := range f {
239
+ f[i] = make([][4]int, n+n+1)
240
+ for j := range f[i] {
241
+ for k := range f[i][j] {
242
+ f[i][j][k] = -1
243
+ }
244
+ }
245
+ }
246
+ calc := func(x, y int) int {
247
+ if x == y {
248
+ return 0
249
+ }
250
+ if x < y {
251
+ if x == 0 && y == 2 {
252
+ return 1
253
+ }
254
+ return -1
255
+ }
256
+ if x == 2 && y == 0 {
257
+ return -1
258
+ }
259
+ return 1
260
+ }
261
+ var dfs func(int, int, int) int
262
+ dfs = func(i, j, k int) int {
263
+ if n-i <= j-n {
264
+ return 0
265
+ }
266
+ if i >= n {
267
+ if j-n < 0 {
268
+ return 1
269
+ }
270
+ return 0
271
+ }
272
+ if v := f[i][j][k]; v != -1 {
273
+ return v
274
+ }
275
+ ans := 0
276
+ for l := 0; l < 3; l++ {
277
+ if l == k {
278
+ continue
279
+ }
280
+ ans = (ans + dfs(i+1, j+calc(d[s[i]-'A'], l), l)) % mod
281
+ }
282
+ f[i][j][k] = ans
283
+ return ans
284
+ }
285
+ return dfs(0, n, 3)
286
+ }
108
287
```
109
288
110
289
<!-- tabs: end -->
0 commit comments