Minimum number of sub-strings of a string such that all are power of 5

Given a binary string str. The task is to find the smallest positive integer C such that the binary string can be cut into C pieces (sub-strings) and each sub-string should be a power of 5 with no leading zeros.

Examples:

Input: str = “101101101”
Output: 3
The string “101101101” can be cut into three binary strings “101”, “101”, “101”
each of which is a power of 5.



Input: str = “1111101”
Output: 1
The string “1111101” can be cut into one binary string “1111101” which is
125 in decimal and a power of 5.

Input: str = “00000”
Output: -1
Strings of only zeroes is equivalent to 0 which is not a power of 5.

Approach: This problem is a simple variation of the longest increasing sub-sequence.
Iterate from i = 1 and for every str[j…i] where j = 0 & j < i, we check if the number formed from str[j..i] is a power of 5 then we update the dp[] array with the value of the lowest possible cut size value. After confirming that the number formed from str[j..i] in decimal is a power of 5 we calculate dp[i] = min(dp[i], dp[j] + 1).
This technique is pretty similar to finding the longest increasing sub-sequence.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
#define ll unsigned long long
  
// Function that returns true
// if n is a power of 5
bool ispower(ll n)
{
    if (n < 125)
        return (n == 1 || n == 5 || n == 25);
    if (n % 125 != 0)
        return false;
    else
        return ispower(n / 125);
}
  
// Function to return the decimal
// value of binary equivalent
ll number(string s, int i, int j)
{
    ll ans = 0;
    for (int x = i; x < j; x++) {
        ans = ans * 2 + (s[x] - '0');
    }
    return ans;
}
  
// Function to return the minimum cuts required
int minCuts(string s, int n)
{
    int dp[n + 1];
  
    // Allocating memory for dp[] array
    memset(dp, n + 1, sizeof(dp));
    dp[0] = 0;
  
    // From length 1 to n
    for (int i = 1; i <= n; i++) {
  
        // If previous character is '0' then ignore
        // to avoid number with leading 0s.
        if (s[i - 1] == '0')
            continue;
        for (int j = 0; j < i; j++) {
  
            // Ignore s[j] = '0' starting numbers
            if (s[j] == '0')
                continue;
  
            // Number formed from s[j....i]
            ll num = number(s, j, i);
  
            // Check for power of 5
            if (!ispower(num))
                continue;
  
            // Assigning min value to get min cut possible
            dp[i] = min(dp[i], dp[j] + 1);
        }
    }
  
    // (n + 1) to check if all the strings are traversed
    // and no divisible by 5 is obtained like 000000
    return ((dp[n] < n + 1) ? dp[n] : -1);
}
  
// Driver code
int main()
{
    string s = "101101101";
    int n = s.length();
    cout << minCuts(s, n);
  
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java implementation of the approach
import java.util.*;
  
class GFG
{
  
    // Function that returns true
    // if n is a power of 5
    static boolean ispower(long n)
    {
        if (n < 125)
        {
            return (n == 1 || n == 5 || n == 25);
        }
        if (n % 125 != 0)
        {
            return false;
        }
        else
        {
            return ispower(n / 125);
        }
    }
  
    // Function to return the decimal
    // value of binary equivalent
    static long number(String s, int i, int j) 
    {
        long ans = 0;
        for (int x = i; x < j; x++) 
        {
            ans = ans * 2 + (s.charAt(x) - '0');
        }
        return ans;
    }
  
    // Function to return the minimum cuts required
    static int minCuts(String s, int n)
    {
        int[] dp = new int[n + 1];
  
        // Alongocating memory for dp[] array
        Arrays.fill(dp, n+1);
        dp[0] = 0;
  
        // From length 1 to n
        for (int i = 1; i <= n; i++)
        {
  
            // If previous character is '0' then ignore
            // to avoid number with leading 0s.
            if (s.charAt(i - 1) == '0')
            {
                continue;
            }
            for (int j = 0; j < i; j++) 
            {
  
                // Ignore s[j] = '0' starting numbers
                if (s.charAt(j) == '0'
                {
                    continue;
                }
  
                // Number formed from s[j....i]
                long num = number(s, j, i);
  
                // Check for power of 5
                if (!ispower(num)) 
                {
                    continue;
                }
  
                // Assigning min value to get min cut possible
                dp[i] = Math.min(dp[i], dp[j] + 1);
            }
        }
  
        // (n + 1) to check if all the Strings are traversed
        // and no divisible by 5 is obtained like 000000
        return ((dp[n] < n + 1) ? dp[n] : -1);
    }
  
    // Driver code
    public static void main(String[] args) 
    {
        String s = "101101101";
        int n = s.length();
        System.out.println(minCuts(s, n));
    }
}
  
// This code is contributed by 29AjayKumar

chevron_right


Python 3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python 3 implementation of the approach
   
# Function that returns true
# if n is a power of 5
def ispower( n):
    if (n < 125):
        return (n == 1 or n == 5 or n == 25)
    if (n % 125 != 0):
        return 0
    else:
        return ispower(n // 125)
  
   
# Function to return the decimal
# value of binary equivalent
def number(s, i, j):
    ans = 0
    for x in range( i, j) :
        ans = ans * 2 + (ord(s[x]) - ord('0'))
    return ans
  
# Function to return the minimum cuts required
def minCuts(s, n):
   
    # Allocating memory for dp[] array
    dp=[n+1 for i in range(n+1)]
    dp[0] = 0;
   
    # From length 1 to n
    for i in range(1, n+1) :
   
        # If previous character is '0' then ignore
        # to avoid number with leading 0s.
        if (s[i - 1] == '0'):
            continue
        for j in range(i) :
   
            # Ignore s[j] = '0' starting numbers
            if (s[j] == '0'):
                continue
   
            # Number formed from s[j....i]
            num = number(s, j, i)
   
            # Check for power of 5
            if (not ispower(num)):
                continue
   
            # Assigning min value to get min cut possible
            dp[i] = min(dp[i], dp[j] + 1)
   
    # (n + 1) to check if all the strings are traversed
    # and no divisible by 5 is obtained like 000000
    if dp[n] < n + 1:
        return dp[n] 
    else:
        return  -1
   
# Driver code
if __name__== "__main__":
    s = "101101101"
    n = len(s)
    print(minCuts(s, n))
  
# This code is contributed by ChitraNayal

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# implementation of the approach
using System;
  
class GFG
{
  
    // Function that returns true
    // if n is a power of 5
    static Boolean ispower(long n)
    {
        if (n < 125)
        {
            return (n == 1 || n == 5 || n == 25);
        }
        if (n % 125 != 0)
        {
            return false;
        }
        else
        {
            return ispower(n / 125);
        }
    }
  
    // Function to return the decimal
    // value of binary equivalent
    static long number(String s, int i, int j) 
    {
        long ans = 0;
        for (int x = i; x < j; x++) 
        {
            ans = ans * 2 + (s[x] - '0');
        }
        return ans;
    }
  
    // Function to return the minimum cuts required
    static int minCuts(String s, int n)
    {
        int[] dp = new int[n + 1];
  
        // Alongocating memory for dp[] array
        for (int i = 0; i <= n; i++)
            dp[i]=n+1;
        dp[0] = 0;
  
        // From length 1 to n
        for (int i = 1; i <= n; i++)
        {
  
            // If previous character is '0' then ignore
            // to avoid number with leading 0s.
            if (s[i - 1] == '0')
            {
                continue;
            }
            for (int j = 0; j < i; j++) 
            {
  
                // Ignore s[j] = '0' starting numbers
                if (s[j] == '0'
                {
                    continue;
                }
  
                // Number formed from s[j....i]
                long num = number(s, j, i);
  
                // Check for power of 5
                if (!ispower(num)) 
                {
                    continue;
                }
  
                // Assigning min value to get min cut possible
                dp[i] = Math.Min(dp[i], dp[j] + 1);
            }
        }
  
        // (n + 1) to check if all the Strings are traversed
        // and no divisible by 5 is obtained like 000000
        return ((dp[n] < n + 1) ? dp[n] : -1);
    }
  
    // Driver code
    public static void Main(String[] args) 
    {
        String s = "101101101";
        int n = s.Length;
        Console.WriteLine(minCuts(s, n));
    }
}
  
/* This code contributed by PrinciRaj1992 */

chevron_right


PHP

filter_none

edit
close

play_arrow

link
brightness_4
code

<?php
// PHP implementation of the approach 
  
// Function that returns true 
// if n is a power of 5 
function ispower($n
    if ($n < 125) 
        return ($n == 1 || $n == 5 || $n == 25); 
    if ($n % 125 != 0) 
        return false; 
    else
        return ispower($n / 125); 
  
// Function to return the decimal 
// value of binary equivalent 
function number($s, $i, $j
    $ans = 0; 
    for ($x = $i; $x < $j; $x++)
    
        $ans = $ans * 2 + (ord($s[$x]) - ord('0')); 
    
    return $ans
  
// Function to return the minimum cuts required 
function minCuts($s, $n
    // Allocating memory for dp[] array 
    $dp = array_fill(0,$n + 1,$n + 1); 
      
    $dp[0] = 0; 
  
    // From length 1 to n 
    for ($i = 1; $i <= $n; $i++) 
    
  
        // If previous character is '0' then ignore 
        // to avoid number with leading 0s. 
        if ($s[$i - 1] == '0'
            continue
        for ($j = 0; $j < $i; $j++) 
        
  
            // Ignore s[j] = '0' starting numbers 
            if ($s[$j] == '0'
                continue
  
            // Number formed from s[j....i] 
            $num = number($s, $j, $i); 
  
            // Check for power of 5 
            if (!ispower($num)) 
                continue
  
            // Assigning min value to get min cut possible 
            $dp[$i] = min($dp[$i], $dp[$j] + 1); 
        
    
  
    // (n + 1) to check if all the strings are traversed 
    // and no divisible by 5 is obtained like 000000 
    return (($dp[$n] < $n + 1) ? $dp[$n] : -1); 
  
    // Driver code 
    $s = "101101101"
    $n = strlen($s); 
    echo minCuts($s, $n); 
  
    // This code is contributed by AnkitRai01
  
?>

chevron_right


Output:

3

Time complexity: O(n2)
Space complexity: O(n)



My Personal Notes arrow_drop_up

Competitive Programmer, Full Stack Developer, Technical Content Writer, Machine Learner

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.