61
61
62
62
<!-- 这里可写通用的实现逻辑 -->
63
63
64
- 前缀和统计每个位置各个字母出现的次数。然后根据 count 枚举子字符串左右端点,check 是否满足条件,是则 ans 加 1。
64
+ ** 方法一:枚举 + 滑动窗口 **
65
65
66
- 最后返回 ans。
66
+ 我们可以在 $[ 1..26] $ 范围内枚举子串的字母种类数 $x$,那么子串长度就是 $count \times x$。
67
+
68
+ 接下来,我们将当前子串长度作为窗口的大小,统计窗口大小中有多少种字母的个数为 $count$,记录在 $y$ 中。如果此时 $x = y$,说明当前窗口中的字母个数都为 $count$,那么就可以将答案加一。
69
+
70
+ 时间复杂度 $O(n \times C)$,空间复杂度 $O(C)$。其中 $n$ 为字符串 $s$ 的长度,而 $C$ 为字母的种类数,本题中 $C = 26$。
67
71
68
72
<!-- tabs:start -->
69
73
74
78
``` python
75
79
class Solution :
76
80
def equalCountSubstrings (self , s : str , count : int ) -> int :
77
- n = len (s)
78
- if count > n:
79
- return 0
80
- counter = [[0 ] * 26 for _ in range (n + 1 )]
81
-
82
- def check (i , j ):
83
- c1 = counter[i]
84
- c2 = counter[j + 1 ]
85
- for k in range (26 ):
86
- if c2[k] == 0 or c1[k] == c2[k]:
87
- continue
88
- if c2[k] - c1[k] != count:
89
- return False
90
- return True
91
-
92
81
ans = 0
93
- for i, c in enumerate (s):
94
- idx = ord (c) - ord (' a' )
95
- for j in range (26 ):
96
- counter[i + 1 ][j] = counter[i][j]
97
- counter[i + 1 ][idx] = counter[i][idx] + 1
98
- l = 0
99
- for _ in range (26 ):
100
- l += count
101
- j = i - l + 1
102
- if j < 0 :
103
- break
104
- ans += check(j, i)
82
+ for x in range (1 , 27 ):
83
+ m = count * x
84
+ if m > len (s):
85
+ break
86
+ cnt = Counter()
87
+ y = 0
88
+ for i, c in enumerate (s):
89
+ cnt[c] += 1
90
+ y += cnt[c] == count
91
+ y -= cnt[c] == count + 1
92
+ j = i - m
93
+ if j >= 0 :
94
+ cnt[s[j]] -= 1
95
+ y += cnt[s[j]] == count
96
+ y -= cnt[s[j]] == count - 1
97
+ ans += x == y
105
98
return ans
106
99
```
107
100
@@ -112,44 +105,39 @@ class Solution:
112
105
``` java
113
106
class Solution {
114
107
public int equalCountSubstrings (String s , int count ) {
115
- int n = s. length();
116
- if (count > n) {
117
- return 0 ;
118
- }
119
- int [][] counter = new int [n + 1 ][26 ];
120
108
int ans = 0 ;
121
- for (int i = 0 ; i < n; ++ i) {
122
- int idx = s. charAt(i) - ' a' ;
123
- for (int j = 0 ; j < 26 ; ++ j) {
124
- counter[i + 1 ][j] = counter[i][j];
125
- }
126
- counter[i + 1 ][idx] = counter[i][idx] + 1 ;
127
- int l = 0 ;
128
- for (int k = 0 ; k < 26 ; ++ k) {
129
- l += count;
130
- int j = i - l + 1 ;
131
- if (j < 0 ) {
132
- break ;
109
+ int n = s. length();
110
+ for (int x = 1 ; x < 27 && count * x <= n; ++ x) {
111
+ int m = count * x;
112
+ int [] cnt = new int [26 ];
113
+ int y = 0 ;
114
+ for (int i = 0 ; i < n; ++ i) {
115
+ int a = s. charAt(i) - ' a' ;
116
+ ++ cnt[a];
117
+ if (cnt[a] == count) {
118
+ ++ y;
119
+ }
120
+ if (cnt[a] == count + 1 ) {
121
+ -- y;
122
+ }
123
+ int j = i - m;
124
+ if (j >= 0 ) {
125
+ int b = s. charAt(j) - ' a' ;
126
+ -- cnt[b];
127
+ if (cnt[b] == count) {
128
+ ++ y;
129
+ }
130
+ if (cnt[b] == count - 1 ) {
131
+ -- y;
132
+ }
133
+ }
134
+ if (x == y) {
135
+ ++ ans;
133
136
}
134
- ans += check(j, i, count, counter) ? 1 : 0 ;
135
137
}
136
138
}
137
139
return ans;
138
140
}
139
-
140
- private boolean check (int i , int j , int count , int [][] counter ) {
141
- int [] c1 = counter[i];
142
- int [] c2 = counter[j + 1 ];
143
- for (int k = 0 ; k < 26 ; ++ k) {
144
- if (c2[k] == 0 || c1[k] == c2[k]) {
145
- continue ;
146
- }
147
- if (c2[k] - c1[k] != count) {
148
- return false ;
149
- }
150
- }
151
- return true ;
152
- }
153
141
}
154
142
```
155
143
@@ -159,84 +147,105 @@ class Solution {
159
147
class Solution {
160
148
public:
161
149
int equalCountSubstrings(string s, int count) {
162
- int n = s.size();
163
- if (count > n) return 0;
164
- vector<vector<int >> counter(n + 1, vector<int >(26));
165
150
int ans = 0;
166
- for (int i = 0; i < n; ++i) {
167
- int idx = s[ i] - 'a';
168
- for (int j = 0; j < 26; ++j) counter[ i + 1] [ j ] = counter[ i] [ j ] ;
169
- counter[ i + 1] [ idx ] = counter[ i] [ idx ] + 1;
170
- int l = 0;
171
- for (int k = 0; k < 26; ++k) {
172
- l += count;
173
- int j = i - l + 1;
174
- if (j < 0) break;
175
- ans += check(j, i, count, counter);
151
+ int n = s.size();
152
+ int cnt[ 26] ;
153
+ for (int x = 1; x < 27 && count * x <= n; ++x) {
154
+ int m = count * x;
155
+ memset(cnt, 0, sizeof cnt);
156
+ int y = 0;
157
+ for (int i = 0; i < n; ++i) {
158
+ int a = s[ i] - 'a';
159
+ ++cnt[ a] ;
160
+ y += cnt[ a] == count;
161
+ y -= cnt[ a] == count + 1;
162
+ int j = i - m;
163
+ if (j >= 0) {
164
+ int b = s[ j] - 'a';
165
+ --cnt[ b] ;
166
+ y += cnt[ b] == count;
167
+ y -= cnt[ b] == count - 1;
168
+ }
169
+ ans += x == y;
176
170
}
177
171
}
178
172
return ans;
179
173
}
180
-
181
- bool check(int i, int j, int count, vector<vector<int>>& counter) {
182
- auto& c1 = counter[i];
183
- auto& c2 = counter[j + 1];
184
- for (int k = 0; k < 26; ++k) {
185
- if (c2[k] == 0 || c1[k] == c2[k]) continue;
186
- if (c2[k] - c1[k] != count) return false;
187
- }
188
- return true ;
189
- }
190
174
};
191
175
```
192
176
193
177
### **Go**
194
178
195
179
```go
196
- func equalCountSubstrings (s string , count int ) int {
180
+ func equalCountSubstrings(s string, count int) (ans int) {
197
181
n := len(s)
198
- if count > n {
199
- return 0
200
- }
201
- counter := make ([][]int , n+1 )
202
- for i := range counter {
203
- counter[i] = make ([]int , 26 )
204
- }
205
- ans := 0
206
- check := func (i, j int ) bool {
207
- c1 , c2 := counter[i], counter[j+1 ]
208
- for k := 0 ; k < 26 ; k++ {
209
- if c2[k] == 0 || c1[k] == c2[k] {
210
- continue
182
+ for x := 1; x < 27 && x*count <= n; x++ {
183
+ m := x * count
184
+ y := 0
185
+ cnt := [26]int{}
186
+ for i, c := range s {
187
+ a := c - 'a'
188
+ cnt[a]++
189
+ if cnt[a] == count {
190
+ y++
211
191
}
212
- if c2[k]-c1[k] != count {
213
- return false
192
+ if cnt[a] == count+1 {
193
+ y--
214
194
}
215
- }
216
- return true
217
- }
218
- for i , c := range s {
219
- idx := c - ' a'
220
- for j := 0 ; j < 26 ; j++ {
221
- counter[i+1 ][j] = counter[i][j]
222
- }
223
- counter[i+1 ][idx] = counter[i][idx] + 1
224
- l := 0
225
- for k := 0 ; k < 26 ; k++ {
226
- l += count
227
- j := i - l + 1
228
- if j < 0 {
229
- break
195
+ j := i - m
196
+ if j >= 0 {
197
+ b := s[j] - 'a'
198
+ cnt[b]--
199
+ if cnt[b] == count {
200
+ y++
201
+ }
202
+ if cnt[b] == count-1 {
203
+ y--
204
+ }
230
205
}
231
- if check (j, i) {
206
+ if x == y {
232
207
ans++
233
208
}
234
209
}
235
210
}
236
- return ans
211
+ return
237
212
}
238
213
```
239
214
215
+ ### ** JavaScript**
216
+
217
+ ``` js
218
+ /**
219
+ * @param {string} s
220
+ * @param {number} count
221
+ * @return {number}
222
+ */
223
+ var equalCountSubstrings = function (s , count ) {
224
+ let ans = 0 ;
225
+ const n = s .length ;
226
+ for (let x = 1 ; x <= 26 && x * count <= n; ++ x) {
227
+ const m = x * count;
228
+ const cnt = new Array (26 ).fill (0 );
229
+ let y = 0 ;
230
+ for (let i = 0 ; i < n; ++ i) {
231
+ const a = s .charCodeAt (i) - ' a' .charCodeAt (0 );
232
+ ++ cnt[a];
233
+ y += cnt[a] == count;
234
+ y -= cnt[a] == count + 1 ;
235
+ const j = i - m;
236
+ if (j >= 0 ) {
237
+ const b = s .charCodeAt (j) - ' a' .charCodeAt (0 );
238
+ -- cnt[b];
239
+ y += cnt[b] == count;
240
+ y -= cnt[b] == count - 1 ;
241
+ }
242
+ ans += x == y;
243
+ }
244
+ }
245
+ return ans;
246
+ };
247
+ ```
248
+
240
249
### ** ...**
241
250
242
251
```
0 commit comments