70
70
71
71
<!-- 这里可写通用的实现逻辑 -->
72
72
73
- 状态压缩 + 前缀和。
73
+ ** 方法一:前缀异或 + 计数 **
74
74
75
- 相似题目:[ 1371. 每个元音包含偶数次的最长子字符串] ( /solution/1300-1399/1371.Find%20the%20Longest%20Substring%20Containing%20Vowels%20in%20Even%20Counts/README.md )
75
+ 由于字符串中只包含 $10$ 个小写字母,因此可以用一个长度为 $10$ 的二进制数表示字符串中每个字母的奇偶性,其中第 $i$ 位为 $1$ 表示第 $i$ 个字母出现了奇数次,为 $0$ 表示第 $i$ 个字母出现了偶数次。
76
+
77
+ 我们遍历字符串的每个字符,用一个变量 $st$ 维护当前字符串的前缀异或值,用一个数组 $cnt$ 维护每个前缀异或值出现的次数,初始时 $st = 0$, $cnt[ 0] = 1$。
78
+
79
+ 对于当前遍历到的字符,我们更新其前缀异或值。如果当前的前缀异或值出现了 $cnt[ st] $ 次,也就意味着有 $cnt[ st] $ 个子字符串满足所有字母的出现次数均为偶数,因此我们将答案增加 $cnt[ st] $。此外,对于 $0 \le i < 10$,如果当前的前缀异或值 $st$ 的第 $i$ 位为 $1$,那么我们还可以找到一个字母出现了奇数次,我们将答案增加 $cnt[ st \oplus (1 << i)] $。最后,我们将 $st$ 出现的次数增加 $1$。继续遍历下一个字符,直到遍历完整个字符串。
80
+
81
+ 时间复杂度 $O(n \times \Sigma)$,空间复杂度 $O(2^{\Sigma})$,其中 $\Sigma = 10$,而 $n$ 为字符串的长度。
82
+
83
+ 相似题目:
84
+
85
+ - [ 1371. 每个元音包含偶数次的最长子字符串] ( /solution/1300-1399/1371.Find%20the%20Longest%20Substring%20Containing%20Vowels%20in%20Even%20Counts/README.md )
76
86
77
87
<!-- tabs:start -->
78
88
83
93
``` python
84
94
class Solution :
85
95
def wonderfulSubstrings (self , word : str ) -> int :
86
- counter = Counter({0 : 1 })
87
- state = 0
88
- ans = 0
96
+ cnt = Counter({0 : 1 })
97
+ ans = st = 0
89
98
for c in word:
90
- state ^= 1 << (ord (c) - ord (' a ' ))
91
- ans += counter[state ]
99
+ st ^= 1 << (ord (c) - ord (" a " ))
100
+ ans += cnt[st ]
92
101
for i in range (10 ):
93
- ans += counter[state ^ (1 << i)]
94
- counter[state ] += 1
102
+ ans += cnt[st ^ (1 << i)]
103
+ cnt[st ] += 1
95
104
return ans
96
105
```
97
106
@@ -102,62 +111,39 @@ class Solution:
102
111
``` java
103
112
class Solution {
104
113
public long wonderfulSubstrings (String word ) {
105
- int [] counter = new int [1 << 10 ];
106
- counter[0 ] = 1 ;
107
- int state = 0 ;
114
+ int [] cnt = new int [1 << 10 ];
115
+ cnt[0 ] = 1 ;
108
116
long ans = 0 ;
117
+ int st = 0 ;
109
118
for (char c : word. toCharArray()) {
110
- state ^ = ( 1 << (c - ' a' ) );
111
- ans += counter[state ];
119
+ st ^ = 1 << (c - ' a' );
120
+ ans += cnt[st ];
112
121
for (int i = 0 ; i < 10 ; ++ i) {
113
- ans += counter[state ^ (1 << i)];
122
+ ans += cnt[st ^ (1 << i)];
114
123
}
115
- ++ counter[state ];
124
+ ++ cnt[st ];
116
125
}
117
126
return ans;
118
127
}
119
128
}
120
129
```
121
130
122
- ### ** JavaScript**
123
-
124
- ``` js
125
- /**
126
- * @param {string} word
127
- * @return {number}
128
- */
129
- var wonderfulSubstrings = function (word ) {
130
- let counter = new Array (1 << 10 ).fill (0 );
131
- counter[0 ] = 1 ;
132
- let state = 0 ;
133
- let ans = 0 ;
134
- for (let c of word) {
135
- state ^= 1 << (c .charCodeAt (0 ) - ' a' .charCodeAt (0 ));
136
- ans += counter[state];
137
- for (let i = 0 ; i < 10 ; ++ i) {
138
- ans += counter[state ^ (1 << i)];
139
- }
140
- ++ counter[state];
141
- }
142
- return ans;
143
- };
144
- ```
145
-
146
131
### ** C++**
147
132
148
133
``` cpp
149
134
class Solution {
150
135
public:
151
136
long long wonderfulSubstrings(string word) {
152
- vector<int > counter(1024);
153
- counter[ 0] = 1;
137
+ int cnt[ 1024] = {1};
154
138
long long ans = 0;
155
- int state = 0;
139
+ int st = 0;
156
140
for (char c : word) {
157
- state ^= (1 << (c - 'a'));
158
- ans += counter[ state] ;
159
- for (int i = 0; i < 10; ++i) ans += counter[ state ^ (1 << i)] ;
160
- ++counter[ state] ;
141
+ st ^= 1 << (c - 'a');
142
+ ans += cnt[ st] ;
143
+ for (int i = 0; i < 10; ++i) {
144
+ ans += cnt[ st ^ (1 << i)] ;
145
+ }
146
+ ++cnt[ st] ;
161
147
}
162
148
return ans;
163
149
}
@@ -167,23 +153,65 @@ public:
167
153
### **Go**
168
154
169
155
```go
170
- func wonderfulSubstrings(word string) int64 {
171
- counter := make([]int, 1024)
172
- counter[0] = 1
173
- state := 0
174
- var ans int64
156
+ func wonderfulSubstrings(word string) (ans int64) {
157
+ cnt := [1024]int{1}
158
+ st := 0
175
159
for _, c := range word {
176
- state ^= ( 1 << (c - 'a') )
177
- ans += int64(counter[state ])
160
+ st ^= 1 << (c - 'a')
161
+ ans += int64(cnt[st ])
178
162
for i := 0; i < 10; i++ {
179
- ans += int64(counter[state ^(1<<i)])
163
+ ans += int64(cnt[st ^(1<<i)])
180
164
}
181
- counter[state ]++
165
+ cnt[st ]++
182
166
}
183
- return ans
167
+ return
168
+ }
169
+ ```
170
+
171
+ ### ** TypeScript**
172
+
173
+ ``` ts
174
+ function wonderfulSubstrings(word : string ): number {
175
+ const cnt: number [] = new Array (1 << 10 ).fill (0 );
176
+ cnt [0 ] = 1 ;
177
+ let ans = 0 ;
178
+ let st = 0 ;
179
+ for (const c of word ) {
180
+ st ^= 1 << (c .charCodeAt (0 ) - ' a' .charCodeAt (0 ));
181
+ ans += cnt [st ];
182
+ for (let i = 0 ; i < 10 ; ++ i ) {
183
+ ans += cnt [st ^ (1 << i )];
184
+ }
185
+ cnt [st ]++ ;
186
+ }
187
+ return ans ;
184
188
}
185
189
```
186
190
191
+ ### ** JavaScript**
192
+
193
+ ``` js
194
+ /**
195
+ * @param {string} word
196
+ * @return {number}
197
+ */
198
+ var wonderfulSubstrings = function (word ) {
199
+ const cnt = new Array (1024 ).fill (0 );
200
+ cnt[0 ] = 1 ;
201
+ let ans = 0 ;
202
+ let st = 0 ;
203
+ for (const c of word) {
204
+ st ^= 1 << (c .charCodeAt () - ' a' .charCodeAt ());
205
+ ans += cnt[st];
206
+ for (let i = 0 ; i < 10 ; ++ i) {
207
+ ans += cnt[st ^ (1 << i)];
208
+ }
209
+ cnt[st]++ ;
210
+ }
211
+ return ans;
212
+ };
213
+ ```
214
+
187
215
### ** ...**
188
216
189
217
```
0 commit comments