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++ 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;
} |
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));
}
} |
# 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# 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));
}
} |
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(); |
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.