Input: s ="0001111", k =2, queries =[[0,6]]Output: [26]Explanation:
For the query `[0, 6]`, all substrings of `s[0..6] = "0001111"` satisfy the
k-constraint except for the substrings `s[0..5] = "000111"` and `s[0..6] =
"0001111"`.
Input: s ="010101", k =1, queries =[[0,5],[1,4],[2,3]]Output: [15,9,3]Explanation:
The substrings of `s`with a length greater than 3do not satisfy the
k-constraint.
For each query, we want to count the number of substrings in s[li..ri] that satisfy the k-constraint (at most k zeros or at most k ones). Since s can be large, we use prefix sums to quickly count zeros and ones in any substring, and for each starting index, use binary search to find the farthest valid end index.
classSolution {
public: vector<int> countSubstrings(string s, int k, vector<vector<int>>& queries) {
int n = s.size();
vector<int> p0(n+1), p1(n+1);
for (int i =0; i < n; ++i) {
p0[i+1] = p0[i] + (s[i] =='0');
p1[i+1] = p1[i] + (s[i] =='1');
}
vector<int> ans;
for (auto& q : queries) {
int l = q[0], r = q[1], res =0;
for (int i = l; i <= r; ++i) {
int lo = i, hi = r, best = i-1;
while (lo <= hi) {
int mid = (lo + hi) /2;
int c0 = p0[mid+1] - p0[i];
int c1 = p1[mid+1] - p1[i];
if (c0 <= k || c1 <= k) {
best = mid;
lo = mid +1;
} else {
hi = mid -1;
}
}
res += best - i +1;
}
ans.push_back(res);
}
return ans;
}
};
classSolution {
publicint[]countSubstrings(String s, int k, int[][] queries) {
int n = s.length();
int[] p0 =newint[n+1], p1 =newint[n+1];
for (int i = 0; i < n; ++i) {
p0[i+1]= p0[i]+ (s.charAt(i) =='0'? 1 : 0);
p1[i+1]= p1[i]+ (s.charAt(i) =='1'? 1 : 0);
}
int[] ans =newint[queries.length];
for (int qi = 0; qi < queries.length; ++qi) {
int l = queries[qi][0], r = queries[qi][1], res = 0;
for (int i = l; i <= r; ++i) {
int lo = i, hi = r, best = i-1;
while (lo <= hi) {
int mid = (lo + hi) / 2;
int c0 = p0[mid+1]- p0[i];
int c1 = p1[mid+1]- p1[i];
if (c0 <= k || c1 <= k) {
best = mid;
lo = mid + 1;
} else {
hi = mid - 1;
}
}
res += best - i + 1;
}
ans[qi]= res;
}
return ans;
}
}
classSolution {
funcountSubstrings(s: String, k: Int, queries: Array<IntArray>): IntArray {
val n = s.length
val p0 = IntArray(n+1)
val p1 = IntArray(n+1)
for (i in0 until n) {
p0[i+1] = p0[i] + if (s[i] =='0') 1else0 p1[i+1] = p1[i] + if (s[i] =='1') 1else0 }
val ans = IntArray(queries.size)
for ((qi, q) in queries.withIndex()) {
val l = q[0]; val r = q[1]
var res = 0for (i in l..r) {
var lo = i; var hi = r; var best = i-1while (lo <= hi) {
val mid = (lo + hi) / 2val c0 = p0[mid+1] - p0[i]
val c1 = p1[mid+1] - p1[i]
if (c0 <= k || c1 <= k) {
best = mid
lo = mid + 1 } else {
hi = mid - 1 }
}
res += best - i + 1 }
ans[qi] = res
}
return ans
}
}
classSolution:
defcountSubstrings(self, s: str, k: int, queries: list[list[int]]) -> list[int]:
n = len(s)
p0 = [0] * (n+1)
p1 = [0] * (n+1)
for i in range(n):
p0[i+1] = p0[i] + (s[i] =='0')
p1[i+1] = p1[i] + (s[i] =='1')
ans = []
for l, r in queries:
res =0for i in range(l, r+1):
lo, hi, best = i, r, i-1while lo <= hi:
mid = (lo + hi) //2 c0 = p0[mid+1] - p0[i]
c1 = p1[mid+1] - p1[i]
if c0 <= k or c1 <= k:
best = mid
lo = mid +1else:
hi = mid -1 res += best - i +1 ans.append(res)
return ans
impl Solution {
pubfncount_substrings(s: String, k: i32, queries: Vec<Vec<i32>>) -> Vec<i32> {
let n = s.len();
let s = s.as_bytes();
letmut p0 =vec![0; n+1];
letmut p1 =vec![0; n+1];
for i in0..n {
p0[i+1] = p0[i] +if s[i] ==b'0' { 1 } else { 0 };
p1[i+1] = p1[i] +if s[i] ==b'1' { 1 } else { 0 };
}
letmut ans = Vec::new();
for q in queries.iter() {
let l = q[0] asusize;
let r = q[1] asusize;
letmut res =0;
for i in l..=r {
let (mut lo, mut hi, mut best) = (i, r, i-1);
while lo <= hi {
let mid = (lo + hi) /2;
let c0 = p0[mid+1] - p0[i];
let c1 = p1[mid+1] - p1[i];
if c0 <= k || c1 <= k {
best = mid;
lo = mid +1;
} else {
hi = mid -1;
}
}
res += best asi32- i asi32+1;
}
ans.push(res);
}
ans
}
}
⏰ Time complexity: O(Q * N * log N), where Q is the number of queries and N is the length of s. For each query, for each start index, we binary search the end index.
🧺 Space complexity: O(N) for the prefix sum arrays.