@@ -79,32 +79,211 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3300-3399/3320.Co
7979
8080<!-- solution:start -->
8181
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)$。
8395
8496<!-- tabs:start -->
8597
8698#### Python3
8799
88100``` 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
90128```
91129
92130#### Java
93131
94132``` 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+ }
96180```
97181
98182#### C++
99183
100184``` 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+ };
102226```
103227
104228#### Go
105229
106230```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+ }
108287```
109288
110289<!-- tabs: end -->
0 commit comments