Number of sub-sequences of non-zero length of a binary string divisible by 3
Last Updated :
17 Jan, 2023
Given a binary string S of length N, the task is to find the number of sub-sequences of non-zero length which are divisible by 3. Leading zeros in the sub-sequences are allowed.
Examples:
Input: S = “1001”
Output: 5
“11”, “1001”, “0”, “0” and “00” are
the only subsequences divisible by 3.
Input: S = “1”
Output: 0
Naive approach: Generate all the possible sub-sequences and check if they are divisible by 3. Time complexity for this will be O((2N) * N).
Better approach: Dynamic programming can be used to solve this problem. Let’s look at the states of the DP.
DP[i][r] will store the number of sub-sequences of the substring S[i…N-1] such that they give a remainder of (3 – r) % 3 when divided by 3.
Let’s write the recurrence relation now.
DP[i][r] = DP[i + 1][(r * 2 + s[i]) % 3] + DP[i + 1][r]
The recurrence is derived because of the two choices below:
- Include the current index i in the sub-sequence. Thus, the r will be updated as r = (r * 2 + s[i]) % 3.
- Don’t include a current index in the sub-sequence.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
#define N 100
int dp[N][3];
bool v[N][3];
int findCnt(string& s, int i, int r)
{
if (i == s.size()) {
if (r == 0)
return 1;
else
return 0;
}
if (v[i][r])
return dp[i][r];
v[i][r] = 1;
dp[i][r]
= findCnt(s, i + 1, (r * 2 + (s[i] - '0' )) % 3)
+ findCnt(s, i + 1, r);
return dp[i][r];
}
int main()
{
string s = "11" ;
cout << (findCnt(s, 0, 0) - 1);
return 0;
}
|
Java
class GFG
{
static final int N = 100 ;
static int dp[][] = new int [N][ 3 ];
static int v[][] = new int [N][ 3 ];
static int findCnt(String s, int i, int r)
{
if (i == s.length())
{
if (r == 0 )
return 1 ;
else
return 0 ;
}
if (v[i][r] == 1 )
return dp[i][r];
v[i][r] = 1 ;
dp[i][r] = findCnt(s, i + 1 , (r * 2 + (s.charAt(i) - '0' )) % 3 )
+ findCnt(s, i + 1 , r);
return dp[i][r];
}
public static void main (String[] args)
{
String s = "11" ;
System.out.print(findCnt(s, 0 , 0 ) - 1 );
}
}
|
Python3
import numpy as np
N = 100
dp = np.zeros((N, 3 ));
v = np.zeros((N, 3 ));
def findCnt(s, i, r) :
if (i = = len (s)) :
if (r = = 0 ) :
return 1 ;
else :
return 0 ;
if (v[i][r]) :
return dp[i][r];
v[i][r] = 1 ;
dp[i][r] = findCnt(s, i + 1 , (r * 2 +
( ord (s[i]) - ord ( '0' ))) % 3 ) + \
findCnt(s, i + 1 , r);
return dp[i][r];
if __name__ = = "__main__" :
s = "11" ;
print (findCnt(s, 0 , 0 ) - 1 );
|
C#
using System;
class GFG
{
static readonly int N = 100;
static int [,]dp = new int [N, 3];
static int [,]v = new int [N, 3];
static int findCnt(String s, int i, int r)
{
if (i == s.Length)
{
if (r == 0)
return 1;
else
return 0;
}
if (v[i, r] == 1)
return dp[i, r];
v[i, r] = 1;
dp[i, r] = findCnt(s, i + 1, (r * 2 + (s[i] - '0' )) % 3)
+ findCnt(s, i + 1, r);
return dp[i, r];
}
public static void Main(String[] args)
{
String s = "11" ;
Console.Write(findCnt(s, 0, 0) - 1);
}
}
|
Javascript
<script>
var N = 100
var dp = Array.from(Array(N), ()=> Array(3));
var v = Array.from(Array(N), ()=> Array(3));
function findCnt(s, i, r)
{
if (i == s.length) {
if (r == 0)
return 1;
else
return 0;
}
if (v[i][r])
return dp[i][r];
v[i][r] = 1;
dp[i][r]
= findCnt(s, i + 1, (r * 2 + (s[i] - '0' )) % 3)
+ findCnt(s, i + 1, r);
return dp[i][r];
}
var s = "11" ;
document.write( (findCnt(s, 0, 0) - 1));
</script>
|
Time Complexity: O(n)
Auxiliary Space: O(n * 3) ⇒ O(n), where n is the length of the given string.
Share your thoughts in the comments
Please Login to comment...