Open In App

Longest sub-sequence of a binary string divisible by 3

Last Updated : 23 Dec, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given a binary string S of length N, the task is to find the length of the longest sub-sequence in it which is divisible by 3. Leading zeros in the sub-sequences are allowed.
Examples: 
 

Input: S = “1001” 
Output:
The longest sub-sequence divisible by 3 is “1001”. 
1001 = 9 which is divisible by 3.
Input: S = “1011” 
Output: 3 776

Naive approach: Generate all the possible sub-sequences and check if they are divisible by 3. The time complexity for this will be O((2N) * N).

Implementation:

C++




#include <bits/stdc++.h>
 
using namespace std;
 
bool isDivisibleBy3(string s) {
   int n = s.length();
   int num = 0;
   for (int i = 0; i < n; i++) {
       num = num * 2 + (s[i] - '0');
   }
   return (num % 3 == 0);
}
 
int longest(string s) {
   int n = s.length();
   int maxLen = 0;
   for (int i = 0; i < (1 << n); i++) {
       string sub = "";
       for (int j = 0; j < n; j++) {
           if ((i >> j) & 1) {
               sub.push_back(s[j]);
           }
       }
       if (isDivisibleBy3(sub)) {
           maxLen = max(maxLen, (int) sub.length());
       }
   }
   return maxLen;
}
 
int main() {
   string s1 = "101";
   cout <<longest(s1)<<endl;
   return 0;
}


Java




public class Main {
 
    // Function to check if a binary string is divisible by
    // 3
    static boolean isDivisibleBy3(String s)
    {
        int n = s.length();
        int num = 0;
        for (int i = 0; i < n; i++) {
            num = num * 2 + (s.charAt(i) - '0');
        }
        return (num % 3 == 0);
    }
 
    // Function to find the length of the longest substring
    // of a binary string divisible by 3
    static int longest(String s)
    {
        int n = s.length();
        int maxLen = 0;
        for (int i = 0; i < (1 << n); i++) {
            StringBuilder sub = new StringBuilder();
            for (int j = 0; j < n; j++) {
                if (((i >> j) & 1) == 1) {
                    sub.append(s.charAt(j));
                }
            }
            if (isDivisibleBy3(sub.toString())) {
                maxLen = Math.max(maxLen, sub.length());
            }
        }
        return maxLen;
    }
 
    // Main function
    public static void main(String[] args)
    {
        String s1 = "101";
        System.out.println(longest(s1));
    }
}


Python3




def is_divisible_by_3(s):
    n = len(s)
    num = 0
    for i in range(n):
        num = num * 2 + int(s[i])
    return num % 3 == 0
 
def longest(s):
    n = len(s)
    max_len = 0
 
    # Iterate through all possible subsets using bitmasking
    for i in range(1 << n):
        sub = ""
        for j in range(n):
            # Check if j-th bit is set in the bitmask
            if (i >> j) & 1:
                sub += s[j]
 
        # Check if the substring is divisible by 3
        if is_divisible_by_3(sub):
            max_len = max(max_len, len(sub))
 
    return max_len
 
if __name__ == "__main__":
    s1 = "101"
    print(longest(s1))


C#




using System;
 
namespace DivisibleByThree
{
    class Program
    {
        // Function to check if a binary string is divisible by 3
        static bool IsDivisibleBy3(string s)
        {
            int n = s.Length;
            int num = 0;
             
            // Converting binary string to integer representation
            foreach (char c in s)
            {
                num = num * 2 + (c - '0');
            }
             
            // Checking if the number is divisible by 3
            return (num % 3 == 0);
        }
 
        // Function to find the length of the longest substring whose binary
        // representation is divisible by 3
        static int Longest(string s)
        {
            int n = s.Length;
            int maxLen = 0;
             
            // Generating all possible substrings and checking if they are divisible by 3
            for (int i = 0; i < (1 << n); i++)
            {
                string sub = "";
                 
                // Generating substring based on the current bitmask
                for (int j = 0; j < n; j++)
                {
                    if (((i >> j) & 1) == 1)
                    {
                        sub += s[j];
                    }
                }
                 
                // Checking if the generated substring is divisible by 3 and updating maxLen
                if (IsDivisibleBy3(sub))
                {
                    maxLen = Math.Max(maxLen, sub.Length);
                }
            }
             
            // Returning the length of the longest substring divisible by 3
            return maxLen;
        }
 
        static void Main(string[] args)
        {
            string s1 = "101";
             
            // Finding and displaying the length of the longest substring divisible by 3
            Console.WriteLine(Longest(s1));
        }
    }
}


Javascript




function isDivisibleBy3(s) {
    const n = s.length;
    let num = 0;
    for (let i = 0; i < n; i++) {
        num = num * 2 + parseInt(s[i]);
    }
    return num % 3 === 0;
}
 
function longest(s) {
    const n = s.length;
    let maxLen = 0;
 
    // Iterate through all possible subsets using bitmasking
    for (let i = 1; i < (1 << n); i++) {
        let sub = "";
        for (let j = 0; j < n; j++) {
            // Check if j-th bit is set in the bitmask
            if ((i >> j) & 1) {
                sub += s[j];
            }
        }
 
        // Check if the substring is divisible by 3
        if (isDivisibleBy3(sub)) {
            maxLen = Math.max(maxLen, sub.length);
        }
    }
 
    return maxLen;
}
 
// Driver function
const s1 = "101";
console.log(longest(s1));
 
// this code is contributed by Dwaipayan Bandyopadhyay


Output:

2

Time Complexity: O((2^N) * N), N is the length of the binary string.
Auxiliary Space: O(1),as we are not using any extra space.

Efficient approach: Dynamic programming can be used to solve this problem. Let’s look at the states of DP. 
DP[i][r] will store the longest sub-sequence of the substring S[i…N-1] such that it gives a remainder of (3 – r) % 3 when divided by 3
Let’s write the recurrence relation now. 
 

DP[i][r] = max(1 + DP[i + 1][(r * 2 + s[i]) % 3], DP[i + 1][r]) 
 

The recurrence is derived because of the following two choices: 
 

  1. Include the current index i in the sub-sequence. Thus, the r will be updated as r = (r * 2 + s[i]) % 3.
  2. Don’t include the current index in the sub-sequence.

Below is the implementation of the above approach: 
 

C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
#define N 100
 
int dp[N][3];
bool v[N][3];
 
// Function to return the length of the
// largest sub-string divisible by 3
int findLargestString(string& s, int i, int r)
{
    // Base-case
    if (i == s.size()) {
        if (r == 0)
            return 0;
        else
            return INT_MIN;
    }
 
    // If the state has been solved
    // before then return its value
    if (v[i][r])
        return dp[i][r];
 
    // Marking the state as solved
    v[i][r] = 1;
 
    // Recurrence relation
    dp[i][r]
        = max(1 + findLargestString(s, i + 1,
                                    (r * 2 + (s[i] - '0')) % 3),
              findLargestString(s, i + 1, r));
    return dp[i][r];
}
 
// Driver code
int main()
{
    string s = "101";
 
    cout << findLargestString(s, 0, 0);
 
    return 0;
}


Java




// Java implementation of the approach
class GFG
{
 
    final static int N = 100 ;
    final static int INT_MIN = Integer.MIN_VALUE;
     
    static int dp[][] = new int[N][3];
    static int v[][] = new int[N][3];
     
     
    // Function to return the length of the
    // largest sub-string divisible by 3
    static int findLargestString(String s, int i, int r)
    {
        // Base-case
        if (i == s.length())
        {
            if (r == 0)
                return 0;
            else
                return INT_MIN;
        }
     
        // If the state has been solved
        // before then return its value
        if (v[i][r] == 1)
            return dp[i][r];
     
        // Marking the state as solved
        v[i][r] = 1;
     
        // Recurrence relation
        dp[i][r] = Math.max(1 + findLargestString(s, i + 1,
                          (r * 2 + (s.charAt(i) - '0')) % 3),
                            findLargestString(s, i + 1, r));
        return dp[i][r];
    }
     
    // Driver code
    public static void main (String[] args)
    {
        String s = "101";
     
        System.out.print(findLargestString(s, 0, 0));
    }
}
 
// This code is contributed by AnkitRai01


Python3




# Python3 implementation of the approach
import numpy as np
import sys
 
N = 100
INT_MIN = -(sys.maxsize - 1)
 
dp = np.zeros((N, 3));
v = np.zeros((N, 3));
 
# Function to return the length of the
# largest sub-string divisible by 3
def findLargestString(s, i, r) :
 
    # Base-case
    if (i == len(s)) :
        if (r == 0) :
            return 0;
        else :
            return INT_MIN;
 
    # If the state has been solved
    # before then return its value
    if (v[i][r]) :
        return dp[i][r];
 
    # Marking the state as solved
    v[i][r] = 1;
 
    # Recurrence relation
    dp[i][r] = max(1 + findLargestString(s, i + 1,
                  (r * 2 + (ord(s[i]) - ord('0'))) % 3),
                       findLargestString(s, i + 1, r));
                 
    return dp[i][r];
 
# Driver code
if __name__ == "__main__" :
 
    s = "101";
 
    print(findLargestString(s, 0, 0));
 
# This code is contributed by AnkitRai01


C#




// C# implementation of the approach
using System;
using System.Collections.Generic;
 
class GFG
{
 
    readonly static int N = 100 ;
    readonly static int INT_MIN = int.MinValue;
     
    static int [,]dp = new int[N, 3];
    static int [,]v = new int[N, 3];
     
    // Function to return the length of the
    // largest sub-string divisible by 3
    static int findLargestString(String s, int i, int r)
    {
        // Base-case
        if (i == s.Length)
        {
            if (r == 0)
                return 0;
            else
                return INT_MIN;
        }
     
        // If the state has been solved
        // before then return its value
        if (v[i, r] == 1)
            return dp[i, r];
     
        // Marking the state as solved
        v[i, r] = 1;
     
        // Recurrence relation
        dp[i, r] = Math.Max(1 + findLargestString(s, i + 1,
                                (r * 2 + (s[i] - '0')) % 3),
                            findLargestString(s, i + 1, r));
        return dp[i, r];
    }
     
    // Driver code
    public static void Main(String[] args)
    {
        String s = "101";
     
        Console.Write(findLargestString(s, 0, 0));
    }
}
 
// This code is contributed by 29AjayKumar


Javascript




<script>
// Javascript implementation of the approach
var N = 100
 
var dp = Array.from(Array(N), ()=>Array(3));
var v = Array.from(Array(N), ()=>Array(3));
 
// Function to return the length of the
// largest sub-string divisible by 3
function findLargestString(s, i, r)
{
    // Base-case
    if (i == s.length) {
        if (r == 0)
            return 0;
        else
            return -1000000000;
    }
 
    // If the state has been solved
    // before then return its value
    if (v[i][r])
        return dp[i][r];
 
    // Marking the state as solved
    v[i][r] = 1;
 
    // Recurrence relation
    dp[i][r]
        = Math.max(1 + findLargestString(s, i + 1,
                                    (r * 2 + (s[i].charCodeAt(0) - '0'.charCodeAt(0))) % 3),
              findLargestString(s, i + 1, r));
    return dp[i][r];
}
 
// Driver code
var s = "101";
document.write( findLargestString(s, 0, 0));
 
// This code is contributed by noob2000.
</script>


Output

2









Time Complexity: O(n)
Auxiliary Space: O(n * 3) ⇒ O(n), where n is the length of the given string.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads