Number of alternating substrings from a given Binary String
Last Updated :
14 Oct, 2023
Given a binary string of size N, the task is to count the number of alternating substrings that are present in the string S.
Examples:
Input: S = “0010”
Output: 7
Explanation:
All the substring of the string S are: {“0”, “00”, “001”, “0010”, “0”, “01”, “010”, “1”, “10”, “0”}
Strings that are alternating: {“0”, “0”, “01”, “010”, “1”, “10”, “0”}.
Hence, the answer is 7.
Input: S = “010”
Output: 6
Naive Approach: The simplest approach to solve this problem is to first, find all the substrings of the string S, then check for every string if it is alternating or not.
Time Complexity: O(N3)
Auxiliary Space: O(N2)
Efficient Approach: This problem has Overlapping Subproblems property and Optimal Substructure property. So this problem can be solved using Dynamic Programming. Follow the steps below to solve this problem:
- Declare a dp array, where dp[i][j] stores the number of alternating strings that start with char i and are in the range [j, N-1].
- Iterate in the range [N-1, 0] using the variable i and perform the following steps:
- If i is equal to N-1, then if current character is ‘1’, then assign 1 to dp[1][i], otherwise assign 1 to dp[0][i].
- Else, if current character is ‘0’, then update dp[0][i] to 1+dp[1][i+1], otherwise, update dp[1][i] to 1+dp[0][i+1].
- Initialize a variable say ans as 0 to store the number of substrings that are alternating.
- Iterate in the range [0, N-1] using the variable i and perform the following steps:
- Update ans as max of dp[0][i] and dp[1][i].
- Finally, print the value obtained in ans as the answer.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int countAlternatingSubstrings(string S, int N)
{
vector<vector< int > > dp(2, vector< int >(N, 0));
for ( int i = N - 1; i >= 0; i--) {
if (i == N - 1) {
if (S[i] == '1' )
dp[1][i] = 1;
else
dp[0][i] = 1;
}
else {
if (S[i] == '0' )
dp[0][i] = 1 + dp[1][i + 1];
else
dp[1][i] = 1 + dp[0][i + 1];
}
}
int ans = 0;
for ( int i = 0; i < N; i++) {
ans += max(dp[0][i], dp[1][i]);
}
return ans;
}
int main()
{
string S = "0010" ;
int N = S.length();
cout << countAlternatingSubstrings(S, N);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int countAlternatingSubstrings(String S, int N)
{
int [][] dp = new int [ 2 ][N];
for ( int i = 0 ; i < 2 ; i++)
{
for ( int j = 0 ; j < N; j++)
{
dp[i][j] = 0 ;
}
}
for ( int i = N - 1 ; i >= 0 ; i--)
{
if (i == N - 1 )
{
if (S.charAt(i) == '1' )
dp[ 1 ][i] = 1 ;
else
dp[ 0 ][i] = 1 ;
}
else
{
if (S.charAt(i) == '0' )
dp[ 0 ][i] = 1 + dp[ 1 ][i + 1 ];
else
dp[ 1 ][i] = 1 + dp[ 0 ][i + 1 ];
}
}
int ans = 0 ;
for ( int i = 0 ; i < N; i++)
{
ans += Math.max(dp[ 0 ][i], dp[ 1 ][i]);
}
return ans;
}
public static void main(String[] args)
{
String S = "0010" ;
int N = S.length();
System.out.print(countAlternatingSubstrings(S, N));
}
}
|
Python3
def countAlternatingSubstrings(S, N):
dp = [[ 0 for i in range (N)]
for i in range ( 2 )]
for i in range (N - 1 , - 1 , - 1 ):
if (i = = N - 1 ):
if (S[i] = = '1' ):
dp[ 1 ][i] = 1
else :
dp[ 0 ][i] = 1
else :
if (S[i] = = '0' ):
dp[ 0 ][i] = 1 + dp[ 1 ][i + 1 ]
else :
dp[ 1 ][i] = 1 + dp[ 0 ][i + 1 ]
ans = 0
for i in range (N):
ans + = max (dp[ 0 ][i], dp[ 1 ][i])
return ans
if __name__ = = '__main__' :
S = "0010"
N = len (S)
print (countAlternatingSubstrings(S, N))
|
C#
using System;
class GFG{
static int countAlternatingSubstrings( string S, int N)
{
int [,] dp = new int [2, N];
for ( int i = 0; i < 2; i++)
{
for ( int j = 0; j < N; j++)
{
dp[i, j] = 0;
}
}
for ( int i = N - 1; i >= 0; i--)
{
if (i == N - 1)
{
if (S[i] == '1' )
dp[1, i] = 1;
else
dp[0, i] = 1;
}
else
{
if (S[i] == '0' )
dp[0, i] = 1 + dp[1, i + 1];
else
dp[1, i] = 1 + dp[0, i + 1];
}
}
int ans = 0;
for ( int i = 0; i < N; i++)
{
ans += Math.Max(dp[0, i], dp[1, i]);
}
return ans;
}
public static void Main()
{
string S = "0010" ;
int N = S.Length;
Console.Write(countAlternatingSubstrings(S, N));
}
}
|
Javascript
<script>
function countAlternatingSubstrings(S, N)
{
var dp = new Array(2);
dp[0] = Array(N).fill(0);
dp[1] = Array(N).fill(0);
var i;
for (i = N - 1; i >= 0; i--)
{
if (i == N - 1)
{
if (S[i] == '1' )
dp[1][i] = 1;
else
dp[0][i] = 1;
}
else
{
if (S[i] == '0' )
dp[0][i] = 1 + dp[1][i + 1];
else
dp[1][i] = 1 + dp[0][i + 1];
}
}
var ans = 0;
for (i = 0; i < N; i++)
{
ans += Math.max(dp[0][i], dp[1][i]);
}
return ans;
}
var S = "0010" ;
var N = S.length;
document.write(countAlternatingSubstrings(S, N));
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(N)
Efficient approach: Space optimization O(1)
In previous approach we the current value dp[i] is only depend upon the previous 2 values i.e. dp[0][i-1], dp[1][i-1] . So to optimize the space we can keep track of previous and current values by the help of variables prev0, prev1 and curr0 ,curr1 which will reduce the space complexity from O(N) to O(1).
Implementation Steps:
- Create 2 variables prev0 and prev1 to keep track of previous values of DP.
- Initialize base case prev0 = prev1 = 0.
- Create variables curr0 and curr1 to store current value.
- Iterate over subproblem using loop and update curr0 , curr1.
- After every iteration update prev0 and prev1 for further iterations.
- At last return ans containing maximum of curr0 and curr1.
C++
#include <bits/stdc++.h>
using namespace std;
int countAlternatingSubstrings(string S, int N)
{
int prev0 = 0, prev1 = 0;
int curr0, curr1;
int ans = 0;
for ( int i = N - 1; i >= 0; i--) {
if (S[i] == '0' ) {
curr0 = 1 + prev1;
curr1 = 0;
}
else {
curr1 = 1 + prev0;
curr0 = 0;
}
ans += max(curr0, curr1);
prev0 = curr0;
prev1 = curr1;
}
return ans;
}
int main()
{
string S = "0010" ;
int N = S.length();
cout << countAlternatingSubstrings(S, N);
return 0;
}
|
Java
import java.util.*;
class Main {
public static int countAlternatingSubstrings(String S, int N) {
int prev0 = 0 , prev1 = 0 ;
int curr0, curr1;
int ans = 0 ;
for ( int i = N - 1 ; i >= 0 ; i--) {
if (S.charAt(i) == '0' ) {
curr0 = 1 + prev1;
curr1 = 0 ;
}
else {
curr1 = 1 + prev0;
curr0 = 0 ;
}
ans += Math.max(curr0, curr1);
prev0 = curr0;
prev1 = curr1;
}
return ans;
}
public static void main(String[] args) {
String S = "0010" ;
int N = S.length();
System.out.println(countAlternatingSubstrings(S, N));
}
}
|
Python
def count_alternating_substrings_optimized(S):
prev0 = prev1 = curr0 = curr1 = ans = 0
for i in range ( len (S) - 1 , - 1 , - 1 ):
if S[i] = = '0' :
curr0, curr1 = 1 + prev1, 0
else :
curr1, curr0 = 1 + prev0, 0
ans + = max (curr0, curr1)
prev0, prev1 = curr0, curr1
return ans
if __name__ = = "__main__" :
S = "0010"
print (count_alternating_substrings_optimized(S))
|
C#
using System;
class MainClass {
public static int CountAlternatingSubstrings( string S, int N) {
int prev0 = 0, prev1 = 0;
int curr0, curr1;
int ans = 0;
for ( int i = N - 1; i >= 0; i--) {
if (S[i] == '0' ) {
curr0 = 1 + prev1;
curr1 = 0;
}
else {
curr1 = 1 + prev0;
curr0 = 0;
}
ans += Math.Max(curr0, curr1);
prev0 = curr0;
prev1 = curr1;
}
return ans;
}
public static void Main( string [] args) {
string S = "0010" ;
int N = S.Length;
Console.WriteLine(CountAlternatingSubstrings(S, N));
}
}
|
Javascript
function countAlternatingSubstrings(S) {
let prev0 = 0;
let prev1 = 0;
let curr0, curr1;
let ans = 0;
for (let i = S.length - 1; i >= 0; i--) {
if (S[i] === '0' ) {
curr0 = 1 + prev1;
curr1 = 0;
}
else {
curr1 = 1 + prev0;
curr0 = 0;
}
ans += Math.max(curr0, curr1);
prev0 = curr0;
prev1 = curr1;
}
return ans;
}
const S = "0010" ;
const result = countAlternatingSubstrings(S);
console.log(result);
|
Time Complexity: O(N)
Auxiliary Space: O(1)
Share your thoughts in the comments
Please Login to comment...