The Number Of Good Substrings
You are given a binary string s s s (recall that a string is binary if each character is either 0 0 0 or 1 1 1).
Let f ( t ) f(t) f(t) be the decimal representation of integer t t t written in binary form (possibly with leading zeroes). For example f ( 011 ) = 3 , f ( 00101 ) = 5 , f ( 00001 ) = 1 , f ( 10 ) = 2 , f ( 000 ) = 0 f(011) = 3, f(00101) = 5, f(00001) = 1, f(10) = 2, f(000) = 0 f(011)=3,f(00101)=5,f(00001)=1,f(10)=2,f(000)=0 and f ( 000100 ) = 4 f(000100) = 4 f(000100)=4.
The substring s l , s l + 1 , … , s r s_{l}, s_{l+1}, \dots , s_{r} sl,sl+1,…,sr is good if r − l + 1 = f ( s l … s r ) r - l + 1 = f(s_l \dots s_r) r−l+1=f(sl…sr).
For example string s = 1011 s = 1011 s=1011 has 5 5 5 good substrings: s 1 … s 1 = 1 s_1 \dots s_1 = 1 s1…s1=1, s 3 … s 3 = 1 s_3 \dots s_3 = 1 s3…s3=1, s 4 … s 4 = 1 s_4 \dots s_4 = 1 s4…s4=1, s 1 … s 2 = 10 s_1 \dots s_2 = 10 s1…s2=10 and s 2 … s 4 = 011 s_2 \dots s_4 = 011 s2…s4=011.
Your task is to calculate the number of good substrings of string s s s.
You have to answer t t t independent queries.
Input
The first line contains one integer t t t ( 1 ≤ t ≤ 1000 1 \le t \le 1000 1≤t≤1000) — the number of queries.
The only line of each query contains string s s s ( 1 ≤ ∣ s ∣ ≤ 2 ⋅ 1 0 5 1 \le |s| \le 2 \cdot 10^5 1≤∣s∣≤2⋅105), consisting of only digits 0 0 0 and 1 1 1.
It is guaranteed that ∑ i = 1 t ∣ s i ∣ ≤ 2 ⋅ 1 0 5 \sum\limits_{i=1}^{t} |s_i| \le 2 \cdot 10^5 i=1∑t∣si∣≤2⋅105.
Output
For each query print one integer — the number of good substrings of string s s s.
Example
i n p u t \tt input input |
---|
4 0110 0101 00001000 0001000 |
o u t p u t \tt output output |
4 3 4 3 |
Tutorial
由题意得字符串 s s s 的长度最长为 2 ⋅ 1 0 5 2 \cdot 10 ^ 5 2⋅105,所以只需要判断最长为 18 18 18 的子字符串即可,由于前导零不会对数产生影响,因此我们可以用前导零凑数,如果当前长度加上前导零的长度大于当前可以表示的数,那么一定可以是一个 g o o d s u b s t r i n g s \tt good substrings goodsubstrings
此解法时间复杂度为 O ( n log n ) \mathcal O(n\log n) O(nlogn)
Solution
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
void solve() {
int ans = 0;
string s;
cin >> s;
vector<int> pre(s.size() + 1);
for (int i = 0; i < s.size(); ++i) {
if (s[i] == '0') {
pre[i + 1] = pre[i] + 1;
}
}
for (int r = 0; r < s.size(); ++r) {
int mid = 0;
for (int l = r; ~l and r - l < 19; --l) {
if (s[l] == '0') {
continue;
}
mid |= 1 << (r - l);
if (mid <= r - l + 1 + pre[l]) {
++ans;
}
}
}
cout << ans << endl;
}
signed main() {
int Test; cin >> Test; while (Test--)
solve();
return 0;
}