Open In App

Count of Valid Partitions such that all Partitions lie in Range [1, L]

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

Given a string S containing only digits and an integer L, find the number of ways to partition the given string such that each partition forms a number that lies between the range [1, L]. Since the answer may be very large, return the answer modulo 109+7.

Examples:

Input: S = “1000”, L = 10000
Output: 1
Explanation: The only possible partition is [1000]

Input: S = “1317”, L = 2000
Output: 8
Explanation: Possible partitions are [1317], [131, 7], [13, 17], [1, 317], [13, 1, 7], [1, 31, 7], [1, 3, 17], [1, 3, 1, 7]

Approach: To solve the problem follow the below idea:

The idea is to generate all possible partitions using recursion , if the current partition starts with zero then skip it as no number in the range [1, L] starts with 0, and finally if we found one way of generating different valid partitions from given string then increment the answer by 1. We can further reduce the time complexity using memoization.

Steps to solve the problem:

  • Initialize a variable num to keep track of the current partition being formed and ans to keep track of total valid partitions.
  • Iterate over the substring starting from the current index i up to the end of the string.
  • If the current character at index i is ‘0’, it cannot be a part of any valid partition as no number in range [1, L] starts with 0, so return 0.
  • For each digit, update num by appending the digit and check if the number num is less than or equal to the limit L.
    • If num is less than or equal to L, make a recursive call to solver with the updated index j+1. This represents the scenario where we continue forming the current number num and move to the next character.
    • If num is greater than L, then break the loop.
  • If we have reached the end of the string (i == s.size()), return 1. This represents a valid way to split the string.
  • Accumulate the results (ans) from all valid recursive calls.

Below is the implementation of the above approach:

C++14




// C++ code for the above approach:
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the number of ways
// to split the string
int solver(const string& s, long L, int i, vector<int>& dp)
{
    // Base case: Reached end of string,
    // one valid way to split
    if (i == s.size())
        return 1;
 
    // Base case: Current character is '0',
    // cannot form a valid number
    if (s[i] == '0')
        return 0;
 
    // Check if result for current index 'i'
    // is already computed
    if (dp[i] != -1)
        return dp[i];
 
    int ans = 0;
    long num = 0;
 
    // Iterate over the substring
    //  starting from current index 'i'
    for (int j = i; j < s.size(); j++) {
        // Form the current number by
        //  appending digits
        num = num * 10 + s[j] - '0';
 
        // If the formed number exceeds
        // the limit 'L', break the loop
        if (num > L)
            break;
 
        // Recursively call with updated index
        // and accumulate results
        ans += solver(s, L, j + 1, dp);
        ans %= 1000000007;
    }
 
    // Memoize the result for current index 'i'
    return dp[i] = ans;
}
 
// Main function to find the number of ways
int NumberOfWays(string s, int L)
{
    // Initialize a vector for memoization
    vector<int> dp(s.size(), -1);
 
    // Call the solver function
    return solver(s, L, 0, dp);
}
 
int main()
{
    string s = "1000";
    int L = 10000;
 
    // Call the function and print the result
    cout << NumberOfWays(s, L);
    return 0;
}


Java




import java.util.Arrays;
 
public class Main {
    // Function to find the number of ways to split the
    // string
    static int solver(String s, long L, int i, int[] dp)
    {
        // Base case: Reached the end of the string, one
        // valid way to split
        if (i == s.length())
            return 1;
 
        // Base case: Current character is '0', cannot form
        // a valid number
        if (s.charAt(i) == '0')
            return 0;
 
        // Check if the result for the current index 'i' is
        // already computed
        if (dp[i] != -1)
            return dp[i];
 
        int ans = 0;
        long num = 0;
 
        // Iterate over the substring starting from the
        // current index 'i'
        for (int j = i; j < s.length(); j++) {
            // Form the current number by appending digits
            num = num * 10 + s.charAt(j) - '0';
 
            // If the formed number exceeds the limit 'L',
            // break the loop
            if (num > L)
                break;
 
            // Recursively call with an updated index and
            // accumulate results
            ans += solver(s, L, j + 1, dp);
            ans %= 1000000007;
        }
 
        // Memoize the result for the current index 'i'
        dp[i] = ans;
        return ans;
    }
 
    // Main function to find the number of ways
    static int numberOfWays(String s, int L)
    {
        // Initialize an array for memoization
        int[] dp = new int[s.length()];
        Arrays.fill(dp, -1);
 
        // Call the solver function
        return solver(s, L, 0, dp);
    }
 
    public static void main(String[] args)
    {
        String s = "1000";
        int L = 10000;
 
        // Call the function and print the result
        System.out.println(numberOfWays(s, L));
    }
}


Python3




# Python Implementation
 
def solver(s, L, i, dp):
    # Base case: Reached end of string, one valid way to split
    if i == len(s):
        return 1
 
    # Base case: Current character is '0', cannot form a valid number
    if s[i] == '0':
        return 0
 
    # Check if result for current index 'i' is already computed
    if dp[i] != -1:
        return dp[i]
 
    ans = 0
    num = 0
 
    # Iterate over the substring starting from current index 'i'
    for j in range(i, len(s)):
        # Form the current number by appending digits
        num = num * 10 + int(s[j])
 
        # If the formed number exceeds the limit 'L', break the loop
        if num > L:
            break
 
        # Recursively call with updated index and accumulate results
        ans += solver(s, L, j + 1, dp)
        ans %= 1000000007
 
    # Memoize the result for current index 'i'
    dp[i] = ans
    return ans
 
 
def NumberOfWays(s, L):
    # Initialize a list for memoization
    dp = [-1] * len(s)
 
    # Call the solver function
    return solver(s, L, 0, dp)
 
 
s = "1000"
L = 10000
 
# Call the function and print the result
print(NumberOfWays(s, L))
 
# This code is contributed by Sakshi


C#




// C# code for the above approach:
using System;
using System.Collections.Generic;
 
public class GFG
{
    // Function to find the number of
    // ways to split the string
    static int Solver(string s, long L, int i, int[] dp)
    {
        // Base case: Reached end of string,
        // one valid way to split
        if (i == s.Length)
            return 1;
 
        // Base case: Current character is '0',
        // cannot form a valid number
        if (s[i] == '0')
            return 0;
 
        // Check if result for current index
        // 'i' is already computed
        if (dp[i] != -1)
            return dp[i];
 
        int ans = 0;
        long num = 0;
 
        // Iterate over the substring starting
        // from current index 'i'
        for (int j = i; j < s.Length; j++)
        {
            // Form the current number by
            // appending digits
            num = num * 10 + (s[j] - '0');
 
            // If the formed number exceeds the
            // limit 'L', break the loop
            if (num > L)
                break;
 
            // Recursively call with updated index
            // and accumulate results
            ans += Solver(s, L, j + 1, dp);
            ans %= 1000000007;
        }
 
        // Memoize the result for current index 'i'
        return dp[i] = ans;
    }
 
    // Main function to find the
    // number of ways
    static int NumberOfWays(string s, int L)
    {
        // Initialize an array for memoization
        int[] dp = new int[s.Length];
        Array.Fill(dp, -1);
 
        // Call the Solver function
        return Solver(s, L, 0, dp);
    }
 
    // Driver code
    public static void Main(string[] args)
    {
        string s = "1000";
        int L = 10000;
 
        // Call the function and print the result
        Console.WriteLine(NumberOfWays(s, L));
    }
}


Javascript




function solver(s, L, i, dp) {
    // Base case: Reached end of string, one valid way to split
    if (i === s.length) {
        return 1;
    }
 
    // Base case: Current character is '0', cannot form a valid number
    if (s[i] === '0') {
        return 0;
    }
 
    // Check if result for current index 'i' is already computed
    if (dp[i] !== -1) {
        return dp[i];
    }
 
    let ans = 0;
    let num = 0;
 
    // Iterate over the substring starting from current index 'i'
    for (let j = i; j < s.length; j++) {
        // Form the current number by appending digits
        num = num * 10 + parseInt(s[j]);
 
        // If the formed number exceeds the limit 'L', break the loop
        if (num > L) {
            break;
        }
 
        // Recursively call with updated index and accumulate results
        ans += solver(s, L, j + 1, dp);
        ans %= 1000000007;
    }
 
    // Memoize the result for current index 'i'
    dp[i] = ans;
    return ans;
}
 
// Main function to find the number of ways
function NumberOfWays(s, L) {
    // Initialize an array for memoization
    let dp = new Array(s.length).fill(-1);
 
    // Call the solver function
    return solver(s, L, 0, dp);
}
 
// Main function to test the provided example
function main() {
    let s = "1000";
    let L = 10000;
 
    // Call the function and print the result
    console.log(NumberOfWays(s, L));
}
 
// Call the main function to execute the code
main();


Output

1








Time Complexity: O(N2), where N is the length of the input string S.
Auxiliary Space: O(N), which is due to dp[] vector used for memoization.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads