You are given a binary string s
(a string consisting only of the characters '0' and '1'). Your task is to count the number of substrings in s
that contain only the character '1'.
A substring is a contiguous sequence of characters within the string. For example, in s = "0110111"
, the substrings "1", "11", and "111" are all valid substrings consisting only of '1's.
10^9 + 7
.Constraints:
1 <= s.length <= 10^5
s
consists only of '0' and '1'
At first glance, you might think about checking every possible substring of s
to see if it contains only '1's, then count it if it does. However, this brute-force approach would require checking O(n2) substrings, which is not feasible for large strings.
To optimize, notice that all valid substrings must be made up of consecutive '1's. That means we can focus on runs (groups) of consecutive '1's. For each such run, we can count how many substrings can be formed using just those '1's.
The key insight is: for a run of k
consecutive '1's, there are k * (k + 1) / 2
substrings consisting only of '1's (think of all substrings starting and ending within this run).
k * (k + 1) / 2
and add it to the total. Then reset the counter.10^9 + 7
.This approach is efficient because it processes the string in a single pass and does constant work for each character.
Let's use s = "0110111"
as an example:
So, the answer for "0110111"
is 9.
The elegant solution to this problem leverages the observation that all substrings of only '1's are contained within runs of consecutive '1's. By counting the length of each such run and applying the formula for the number of substrings in a sequence, we can efficiently compute the total number of valid substrings in a single pass. This approach is both fast and easy to implement, making it ideal for large input sizes.
class Solution:
def numSub(self, s: str) -> int:
MOD = 10 ** 9 + 7
count = 0
total = 0
for c in s:
if c == '1':
count += 1
else:
total += count * (count + 1) // 2
count = 0
# Add the last run if the string ends with '1'
total += count * (count + 1) // 2
return total % MOD
class Solution {
public:
int numSub(string s) {
const int MOD = 1e9 + 7;
long long count = 0, total = 0;
for (char c : s) {
if (c == '1') {
count++;
} else {
total += count * (count + 1) / 2;
count = 0;
}
}
total += count * (count + 1) / 2;
return total % MOD;
}
};
class Solution {
public int numSub(String s) {
final int MOD = 1000000007;
long count = 0, total = 0;
for (char c : s.toCharArray()) {
if (c == '1') {
count++;
} else {
total += count * (count + 1) / 2;
count = 0;
}
}
total += count * (count + 1) / 2;
return (int)(total % MOD);
}
}
var numSub = function(s) {
const MOD = 1e9 + 7;
let count = 0, total = 0;
for (let c of s) {
if (c === '1') {
count++;
} else {
total += count * (count + 1) / 2;
count = 0;
}
}
total += count * (count + 1) / 2;
return total % MOD;
};