@@ -81,32 +81,165 @@ tags:
81
81
82
82
<!-- solution:start -->
83
83
84
- ### 方法一
84
+ ### 方法一:滑动窗口 + 前缀和
85
+
86
+ 我们用两个变量 $\textit{cnt0}$ 和 $\textit{cnt1}$ 分别记录当前窗口内的 $0$ 和 $1$ 的个数,指针 $i$ 和 $j$ 分别标识窗口的左右边界。用一个数组 $d$ 记录每个位置 $i$ 右边第一个不满足 $k$ 约束的位置,初始时 $d[ i] = n$。另外,用一个长度为 $n + 1$ 的前缀和数组 $\textit{pre}[ i] $ 记录以前 $i$ 个位置作为右边界的满足 $k$ 约束的子字符串的个数。
87
+
88
+ 当我们右移窗口时,如果窗口内的 $0$ 和 $1$ 的个数都大于 $k$,我们将 $d[ i] $ 更新为 $j$,表示位置 $i$ 右边第一个不满足 $k$ 约束的位置。然后我们将 $i$ 右移一位,直到窗口内的 $0$ 和 $1$ 的个数都不大于 $k$。此时,我们可以计算出以 $j$ 为右边界的满足 $k$ 约束的子字符串的个数,即 $j - i + 1$,我们更新到前缀和数组中。
89
+
90
+ 最后,对于每个查询 $[ l, r] $,我们首先找出 $l$ 右边第一个不满足 $k$ 约束的位置 $p$,那么 $p = \min(r + 1, d[ l] )$,那么 $[ l, p - 1] $ 的所有子字符串都满足 $k$ 约束,个数为 $(1 + p - l) \times (p - l) / 2$,然后,我们计算以 $[ p, r] $ 为右边界的满足 $k$ 约束的子字符串的个数,即 $\textit{pre}[ r + 1] - \textit{pre}[ p] $,最后将两者相加即可。
91
+
92
+ 时间复杂度 $O(n + m)$,空间复杂度 $O(n)$。其中 $n$ 和 $m$ 分别为字符串 $s$ 的长度和查询数组 $\textit{queries}$ 的长度。
85
93
86
94
<!-- tabs:start -->
87
95
88
96
#### Python3
89
97
90
98
``` python
91
-
99
+ class Solution :
100
+ def countKConstraintSubstrings (
101
+ self , s : str , k : int , queries : List[List[int ]]
102
+ ) -> List[int ]:
103
+ cnt = [0 , 0 ]
104
+ i, n = 0 , len (s)
105
+ d = [n] * n
106
+ pre = [0 ] * (n + 1 )
107
+ for j, x in enumerate (map (int , s)):
108
+ cnt[x] += 1
109
+ while cnt[0 ] > k and cnt[1 ] > k:
110
+ d[i] = j
111
+ cnt[int (s[i])] -= 1
112
+ i += 1
113
+ pre[j + 1 ] = pre[j] + j - i + 1
114
+ ans = []
115
+ for l, r in queries:
116
+ p = min (r + 1 , d[l])
117
+ a = (1 + p - l) * (p - l) // 2
118
+ b = pre[r + 1 ] - pre[p]
119
+ ans.append(a + b)
120
+ return ans
92
121
```
93
122
94
123
#### Java
95
124
96
125
``` java
97
-
126
+ class Solution {
127
+ public long [] countKConstraintSubstrings (String s , int k , int [][] queries ) {
128
+ int [] cnt = new int [2 ];
129
+ int n = s. length();
130
+ int [] d = new int [n];
131
+ Arrays . fill(d, n);
132
+ long [] pre = new long [n + 1 ];
133
+ for (int i = 0 , j = 0 ; j < n; ++ j) {
134
+ cnt[s. charAt(j) - ' 0' ]++ ;
135
+ while (cnt[0 ] > k && cnt[1 ] > k) {
136
+ d[i] = j;
137
+ cnt[s. charAt(i++ ) - ' 0' ]-- ;
138
+ }
139
+ pre[j + 1 ] = pre[j] + j - i + 1 ;
140
+ }
141
+ int m = queries. length;
142
+ long [] ans = new long [m];
143
+ for (int i = 0 ; i < m; ++ i) {
144
+ int l = queries[i][0 ], r = queries[i][1 ];
145
+ int p = Math . min(r + 1 , d[l]);
146
+ long a = (1L + p - l) * (p - l) / 2 ;
147
+ long b = pre[r + 1 ] - pre[p];
148
+ ans[i] = a + b;
149
+ }
150
+ return ans;
151
+ }
152
+ }
98
153
```
99
154
100
155
#### C++
101
156
102
157
``` cpp
103
-
158
+ class Solution {
159
+ public:
160
+ vector<long long > countKConstraintSubstrings(string s, int k, vector<vector<int >>& queries) {
161
+ int cnt[ 2] {};
162
+ int n = s.size();
163
+ vector<int > d(n, n);
164
+ long long pre[ n + 1] ;
165
+ pre[ 0] = 0;
166
+ for (int i = 0, j = 0; j < n; ++j) {
167
+ cnt[ s[ j] - '0'] ++;
168
+ while (cnt[ 0] > k && cnt[ 1] > k) {
169
+ d[ i] = j;
170
+ cnt[ s[ i++] - '0'] --;
171
+ }
172
+ pre[ j + 1] = pre[ j] + j - i + 1;
173
+ }
174
+ vector<long long > ans;
175
+ for (const auto& q : queries) {
176
+ int l = q[ 0] , r = q[ 1] ;
177
+ int p = min(r + 1, d[ l] );
178
+ long long a = (1LL + p - l) * (p - l) / 2;
179
+ long long b = pre[ r + 1] - pre[ p] ;
180
+ ans.push_back(a + b);
181
+ }
182
+ return ans;
183
+ }
184
+ };
104
185
```
105
186
106
187
#### Go
107
188
108
189
```go
190
+ func countKConstraintSubstrings(s string, k int, queries [][]int) (ans []int64) {
191
+ cnt := [2]int{}
192
+ n := len(s)
193
+ d := make([]int, n)
194
+ for i := range d {
195
+ d[i] = n
196
+ }
197
+ pre := make([]int, n+1)
198
+ for i, j := 0, 0; j < n; j++ {
199
+ cnt[s[j]-'0']++
200
+ for cnt[0] > k && cnt[1] > k {
201
+ d[i] = j
202
+ cnt[s[i]-'0']--
203
+ i++
204
+ }
205
+ pre[j+1] = pre[j] + j - i + 1
206
+ }
207
+ for _, q := range queries {
208
+ l, r := q[0], q[1]
209
+ p := min(r+1, d[l])
210
+ a := (1 + p - l) * (p - l) / 2
211
+ b := pre[r+1] - pre[p]
212
+ ans = append(ans, int64(a+b))
213
+ }
214
+ return
215
+ }
216
+ ```
109
217
218
+ #### TypeScript
219
+
220
+ ``` ts
221
+ function countKConstraintSubstrings(s : string , k : number , queries : number [][]): number [] {
222
+ const cnt: [number , number ] = [0 , 0 ];
223
+ const n = s .length ;
224
+ const d: number [] = Array (n ).fill (n );
225
+ const pre: number [] = Array (n + 1 ).fill (0 );
226
+ for (let i = 0 , j = 0 ; j < n ; ++ j ) {
227
+ cnt [+ s [j ]]++ ;
228
+ while (Math .min (cnt [0 ], cnt [1 ]) > k ) {
229
+ d [i ] = j ;
230
+ cnt [+ s [i ++ ]]-- ;
231
+ }
232
+ pre [j + 1 ] = pre [j ] + j - i + 1 ;
233
+ }
234
+ const ans: number [] = [];
235
+ for (const [l, r] of queries ) {
236
+ const p = Math .min (r + 1 , d [l ]);
237
+ const a = ((1 + p - l ) * (p - l )) / 2 ;
238
+ const b = pre [r + 1 ] - pre [p ];
239
+ ans .push (a + b );
240
+ }
241
+ return ans ;
242
+ }
110
243
```
111
244
112
245
<!-- tabs: end -->
0 commit comments