Given a string S of length N consisting of digits from ‘0’ to ‘9’ .The task is to determine the total number of possible ways to partition the string into K substrings such that :
- Each substring has a minimum length of M (M>=2).
- Substring must start with an even digit number and end with an odd digit number.
Examples:
Input: N = 9, M = 2, k = 3, S = ‘432387429’
Output: 3
Explanation: Following are valid partitions of the string S
43|23|87429, 4323|87|429, 43|2387|429Input: N = 6, M = 3, k = 2, S = ‘546521’
Output: 0
Explanation: There is no way to partition the given string
Approach: The given problem can be recursively solved by
Finding every substring from starting which satisfies the given condition and computing the number of ways to split.
Follow the steps mentioned below to implement the idea:
- Declare a variable (say ans) and initialize to 0.
- Suppose we have to split the given string into X parts starting from ith index then, consider all the prefixes of length at least M starting from ithindex
- If the prefix satisfies the given condition, recursively call the function starting from (current prefix length + i)th index to calculate the total number of ways to split the remaining string into X-1 parts and add it to ans.
- If the value of X is 1 then consider the whole string if its length is greater than M. Otherwise return 0.
- If the current index reaches the end of the string then return 0.
- Return the variable storing the answer.
Below is the implementation of the above approach.
// C++ code to implement the approach #include <bits/stdc++.h> using namespace std;
// Function to count possible ways of splitting int SplitString( int i, int N, int K, int M, string& s)
{ int Firstchar = s[0] - '0' ;
int Lastchar = s[N - 1] - '0' ;
if (Firstchar % 2 != 0 || Lastchar % 2 != 1) {
cout << 0 << endl;
}
if (i == N)
return 0;
if (K == 1) {
int Remchar = N - i;
if (Remchar >= M)
return 1;
return 0;
}
int ans = 0;
int length = 0;
// Loop to check for all possible partition
for ( int j = i; j < N - 1; j++) {
length++;
int CurrentNum = s[j] - '0' ;
int NextNum = s[j + 1] - '0' ;
if (length >= M && CurrentNum % 2 == 1) {
if (NextNum % 2 == 0) {
ans += SplitString(j + 1, N, K - 1, M, s);
}
}
}
return ans;
} // Driver code int main()
{ int N = 9, M = 2, K = 3;
string S = "432387429" ;
// Function call
cout << SplitString(0, N, K, M, S) << endl;
return 0;
} |
// Java code to implement the approach import java.util.*;
class GFG
{ // Function to count possible ways of splitting
static int SplitString( int i, int N, int K, int M,
String s)
{
int Firstchar = s.charAt(i) - '0' ;
int Lastchar = s.charAt(N - 1 ) - '0' ;
if (Firstchar % 2 != 0 || Lastchar % 2 != 1 ) {
return 0 ;
}
if (i == N)
return 0 ;
if (K == 1 ) {
int Remchar = N - i;
if (Remchar >= M)
return 1 ;
return 0 ;
}
int ans = 0 ;
int length = 0 ;
// Loop to check for all possible partition
for ( int j = i; j < N - 1 ; j++) {
length++;
int CurrentNum = s.charAt(j) - '0' ;
int NextNum = s.charAt(j + 1 ) - '0' ;
if (length >= M && CurrentNum % 2 == 1 ) {
if (NextNum % 2 == 0 ) {
ans += SplitString(j + 1 , N, K - 1 , M,
s);
}
}
}
return ans;
}
// Driver code
public static void main(String[] args)
{
int N = 9 , M = 2 , K = 3 ;
String S = "432387429" ;
// Function call
System.out.println(SplitString( 0 , N, K, M, S));
}
} // This code is contributed by karandeep1234. |
# Python code to implement the approach # Function to count possible ways of splitting def SplitString(i, N, K, M, s):
Firstchar = ord (s[i]) - 0
Lastchar = ord (s[N - 1 ]) - 0
if (Firstchar % 2 is not 0 ) or (Lastchar % 2 is not 1 ):
return 0
if (i = = N):
return 0
if (K = = 1 ):
Remchar = N - i
if (Remchar > = M):
return 1
return 0
ans = 0
length = 0
# Loop to check for all possible partition
for j in range (i, N - 1 ):
length + = 1
CurrentNum = ord (s[j]) - 0
NextNum = ord (s[j + 1 ]) - 0
if (length > = M) and (CurrentNum % 2 is 1 ):
if NextNum % 2 is 0 :
ans + = SplitString(j + 1 , N, K - 1 , M, S)
return ans
N, M, K = 9 , 2 , 3
S = "432387429"
# Function call print (SplitString( 0 , N, K, M, S))
# This code is contributed by lokeshmvs21. |
// C# code to implement the approach using System;
public class GFG
{ public static int SplitString( int i, int N, int K, int M, string s)
{
int Firstchar = s[0] - '0' ;
int Lastchar = s[N - 1] - '0' ;
if (((Firstchar % 2) != 0) || ((Lastchar % 2) != 1)) {
Console.WriteLine(0);
}
if (i == N)
return 0;
if (K == 1) {
int Remchar = N - i;
if (Remchar >= M)
return 1;
return 0;
}
int ans = 0;
int length = 0;
// Loop to check for all possible partition
for ( int j = i; j < N - 1; j++) {
length++;
int CurrentNum = s[j] - '0' ;
int NextNum = s[j + 1] - '0' ;
if (length >= M && CurrentNum % 2 == 1) {
if (NextNum % 2 == 0) {
ans += SplitString(j + 1, N, K - 1, M, s);
}
}
}
return ans;
}
public static void Main( string [] args)
{
int N = 9, M = 2, K = 3;
string S = "432387429" ;
// Function call
Console.WriteLine(SplitString(0, N, K, M, S));
}
} // This code is contributed by ksam24000 |
<script> // JavaScrip tcode for the above approach
// Function to count possible ways of splitting
function SplitString(i, N, K, M, s)
{
let Firstchar = s.charAt(i) - '0' ;
let Lastchar = s.charAt(N - 1) - '0' ;
if (Firstchar % 2 != 0 || Lastchar % 2 != 1) {
return 0;
}
if (i == N)
return 0;
if (K == 1) {
let Remchar = N - i;
if (Remchar >= M)
return 1;
return 0;
}
let ans = 0;
let length = 0;
// Loop to check for all possible partition
for (let j = i; j < N - 1; j++) {
length++;
let CurrentNum = s.charAt(j) - '0' ;
let NextNum = s.charAt(j + 1) - '0' ;
if (length >= M && CurrentNum % 2 == 1) {
if (NextNum % 2 == 0) {
ans += SplitString(j + 1, N, K - 1, M,
s);
}
}
}
return ans;
}
// Driver code
let N = 9, M = 2, K = 3;
let S = "432387429" ;
// Function call
document.write(SplitString(0, N, K, M, S));
// This code is contributed by code_hunt. </script> |
Output
3
Time Complexity: O(N*N*K)
Total number of possible states in this problem is N*K as
- There are two variables, the starting index and the given value of K.
- So for every index for a given K we are iterating the whole string,
- Thus for every possible N*K state, we are iterating N times.
Auxiliary Space: O(1)
Efficient Approach using Memoization:
If noticed carefully, you can see the above approach has overlapping sub-problems. So it can be optimized using dynamic programming. The current index and K can uniquely identify each state.
Follow the below steps to implement the idea:
- Write a recursive function as shown above.
- Initialize a 2D array (say dp[][]) to uniquely identify the states:
- If a state is already calculated return the value for that.
- Otherwise, call the recursive function.
- For each recursive call, store the value in the array before returning.
- The final value returned from the function is the required answer.
Below is the implementation of the above approach.
// C++ code to implement the approach #include <bits/stdc++.h> using namespace std;
int dp[1001][1001];
// Function to find the possible ways to split int SplitString( int i, int N, int K, int M, string& s)
{ if (i == N)
return 0;
if (K == 1) {
int Remchar = N - i;
if (Remchar >= M)
return 1;
return 0;
}
if (dp[i][K] != -1)
return dp[i][K];
int ans = 0;
int length = 0;
for ( int j = i; j < N - 1; j++) {
length++;
int CurrentNum = s[j] - '0' ;
int NextNum = s[j + 1] - '0' ;
if (length >= M && CurrentNum % 2 == 1) {
if (NextNum % 2 == 0) {
ans += SplitString(j + 1, N, K - 1, M, s);
}
}
}
return dp[i][K] = ans;
} // Driver code int main()
{ int N = 9, M = 2, K = 3;
string S = "432387429" ;
memset (dp, -1, sizeof (dp));
int Firstchar = S[0] - '0' ;
int Lastchar = S[N - 1] - '0' ;
if (Firstchar % 2 != 0 || Lastchar % 2 != 1) {
cout << 0 << endl;
}
else {
// Function call
cout << SplitString(0, N, K, M, S) << endl;
}
return 0;
} |
// Java code to implement the approach import java.io.*;
import java.util.*;
public class GFG {
// Function to find the possible ways to split
public static int SplitString( int i, int N, int K,
int M, String s)
{
int [][] dp = new int [ 1001 ][ 1001 ];
for ( int m= 0 ;m< 1001 ;m++){
for ( int j= 0 ;j< 1001 ;j++){
dp[m][j] = - 1 ;
}
}
if (i == N)
return 0 ;
if (K == 1 ) {
int Remchar = N - i;
if (Remchar >= M)
return 1 ;
return 0 ;
}
if (dp[i][K] != - 1 )
return dp[i][K];
int ans = 0 ;
int length = 0 ;
for ( int j = i; j < N - 1 ; j++) {
length++;
int CurrentNum = s.charAt(j) - '0' ;
int NextNum = s.charAt(j + 1 ) - '0' ;
if (length >= M && CurrentNum % 2 == 1 ) {
if (NextNum % 2 == 0 ) {
ans += SplitString(j + 1 , N, K - 1 , M,
s);
}
}
}
return dp[i][K] = ans;
}
// Driver code
public static void main(String[] args)
{
int N = 9 , M = 2 , K = 3 ;
String S = "432387429" ;
int Firstchar = S.charAt( 0 ) - '0' ;
int Lastchar = S.charAt(N - 1 ) - '0' ;
if (Firstchar % 2 != 0 || Lastchar % 2 != 1 ) {
System.out.println( 0 );
}
else {
// Function call
System.out.println(SplitString( 0 , N, K, M, S));
}
}
} // This code is contributed by aarohirai2616. |
class GFG :
# Function to find the possible ways to split
@staticmethod
def SplitString( i, N, K, M, s) :
dp = [[ 0 ] * ( 1001 ) for _ in range ( 1001 )]
m = 0
while (m < 1001 ) :
j = 0
while (j < 1001 ) :
dp[m][j] = - 1
j + = 1
m + = 1
if (i = = N) :
return 0
if (K = = 1 ) :
Remchar = N - i
if (Remchar > = M) :
return 1
return 0
if (dp[i][K] ! = - 1 ) :
return dp[i][K]
ans = 0
length = 0
j = i
while (j < N - 1 ) :
length + = 1
CurrentNum = ord (s[j]) - ord ( '0' )
NextNum = ord (s[j + 1 ]) - ord ( '0' )
if (length > = M and CurrentNum % 2 = = 1 ) :
if (NextNum % 2 = = 0 ) :
ans = ans + GFG.SplitString(j + 1 , N, K - 1 , M, s)
j + = 1
dp[i][K] = ans
return dp[i][K]
# Driver code
@staticmethod
def main( args) :
N = 9
M = 2
K = 3
S = "432387429"
Firstchar = ord (S[ 0 ]) - ord ( '0' )
Lastchar = ord (S[N - 1 ]) - ord ( '0' )
if (Firstchar % 2 ! = 0 or Lastchar % 2 ! = 1 ) :
print ( 0 )
else :
# Function call
print (GFG.SplitString( 0 , N, K, M, S))
if __name__ = = "__main__" :
GFG.main([])
# This code is contributed by aadityaburujwale.
|
// C# code to implement the approach using System;
public class GFG {
public static int SplitString( int i, int N, int K,
int M, string s,
int [, ] dp)
{
int Firstchar = s[0] - '0' ;
int Lastchar = s[N - 1] - '0' ;
if (((Firstchar % 2) != 0)
|| ((Lastchar % 2) != 1)) {
Console.WriteLine(0);
}
if (i == N)
return 0;
if (K == 1) {
int Remchar = N - i;
if (Remchar >= M)
return 1;
return 0;
}
if (dp[i, K] != -1)
return dp[i, K];
int ans = 0;
int length = 0;
// Loop to check for all possible partition
for ( int j = i; j < N - 1; j++) {
length++;
int CurrentNum = s[j] - '0' ;
int NextNum = s[j + 1] - '0' ;
if (length >= M && CurrentNum % 2 == 1) {
if (NextNum % 2 == 0) {
ans += SplitString(j + 1, N, K - 1, M,
s, dp);
}
}
}
return dp[i, K] = ans;
}
public static void Main( string [] args)
{
int N = 9, M = 2, K = 3;
string S = "432387429" ;
int [, ] dp = new int [1001, 1001];
// Loop to initially filled the
// table with -1
for ( int i = 0; i < 1001; i++)
for ( int j = 0; j < 1001; j++)
dp[i, j] = -1;
// Function call
Console.WriteLine(SplitString(0, N, K, M, S, dp));
}
} // This code is contributed by garg28harsh. |
// Javascript code to implement the approach // Function to find the possible ways to split function SplitString( i, N, K, M, s,dp)
{ if (i == N)
return 0;
if (K == 1) {
let Remchar = N - i;
if (Remchar >= M)
return 1;
return 0;
}
if (dp[i][K] != -1)
return dp[i][K];
let ans = 0;
let length = 0;
for (let j = i; j < N - 1; j++) {
length++;
let CurrentNum = parseInt(s[j]);
let NextNum = parseInt(s[j+1]);
if (length >= M && CurrentNum % 2 == 1) {
if (NextNum % 2 == 0) {
ans += SplitString(j + 1, N, K - 1, M, s,dp);
}
}
}
return dp[i][K] = ans;
} // Driver code let N = 9, M = 2, K = 3;
let S = "432387429" ;
let dp = new Array(1001);
for (let i=0;i<1001;i++)
dp[i]= new Array(1001);
for (let i=0;i<1001;i++)
for (let j=0;j<1001;j++)
dp[i][j]=-1;
let Firstchar = S[0] - '0' ;
let Lastchar = S[N - 1] - '0' ;
if (Firstchar % 2 != 0 || Lastchar % 2 != 1) {
console.log(0);
}
else {
// Function call
console.log(SplitString(0, N, K, M, S,dp));
}
// This code is contributed by garg28harsh.
|
Output
3
Time Complexity:
Auxiliary Space: O(N*K)
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memorization(top-down) because memorization method needs extra stack space of recursion calls.
Steps to solve this problem :
- Create a table to store the solution of the subproblems.
- Initialize the table with base cases
- Fill up the table iteratively
- Return the final solution
Implementation :
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
int dp[1001][1001];
// Function to find the possible ways to split int SplitString( int N, int K, int M, string& s)
{ // Initialize the base cases
for ( int i = 0; i <= N; i++) {
for ( int j = 0; j <= K; j++) {
// If the length of string is N, then no split is possible
if (i == N)
dp[i][j] = 0;
else if (j == 1) {
// If K = 1, then only one split is allowed
int Remchar = N - i;
if (Remchar >= M)
// If remaining characters in string >= M,
// then only one split is possible
dp[i][j] = 1;
else
dp[i][j] = 0;
} else {
dp[i][j] = -1;
}
}
}
// Fill the DP table
for ( int j = 2; j <= K; j++) {
for ( int i = 0; i < N; i++) {
int ans = 0;
int length = 0;
for ( int k = i; k < N - 1; k++) {
// Incrementing the length of current substring
length++;
// Converting current character to integer
int CurrentNum = s[k] - '0' ;
int NextNum = s[k + 1] - '0' ;
// Checking if the current substring satisfies the given conditions
if (length >= M && CurrentNum % 2 == 1 && NextNum % 2 == 0) {
// Adding the number of ways to split the remaining
// string after the current substring into j-1 parts
ans += dp[k + 1][j - 1];
}
}
dp[i][j] = ans;
}
}
// final answer
return dp[0][K];
} // Driver code int main()
{ int N = 9, M = 2, K = 3;
string S = "432387429" ;
int Firstchar = S[0] - '0' ;
int Lastchar = S[N - 1] - '0' ;
if (Firstchar % 2 != 0 || Lastchar % 2 != 1) {
cout << 0 << endl;
}
else {
// Function call
cout << SplitString(N, K, M, S) << endl;
}
return 0;
} // this code is contributed by bhardwajji |
import java.util.*;
public class Main {
static int [][] dp = new int [ 1001 ][ 1001 ];
// Function to find the possible ways to split
static int SplitString( int N, int K, int M, String s) {
// Initialize the base cases
for ( int i = 0 ; i <= N; i++) {
for ( int j = 0 ; j <= K; j++) {
// If the length of string is N, then no split is possible
if (i == N)
dp[i][j] = 0 ;
else if (j == 1 ) {
// If K = 1, then only one split is allowed
int Remchar = N - i;
if (Remchar >= M)
// If remaining characters in string >= M,
// then only one split is possible
dp[i][j] = 1 ;
else
dp[i][j] = 0 ;
} else {
dp[i][j] = - 1 ;
}
}
}
// Fill the DP table
for ( int j = 2 ; j <= K; j++) {
for ( int i = 0 ; i < N; i++) {
int ans = 0 ;
int length = 0 ;
for ( int k = i; k < N - 1 ; k++) {
// Incrementing the length of current substring
length++;
// Converting current character to integer
int CurrentNum = s.charAt(k) - '0' ;
int NextNum = s.charAt(k + 1 ) - '0' ;
// Checking if the current substring satisfies the given conditions
if (length >= M && CurrentNum % 2 == 1 && NextNum % 2 == 0 ) {
// Adding the number of ways to split the remaining
// string after the current substring into j-1 parts
ans += dp[k + 1 ][j - 1 ];
}
}
dp[i][j] = ans;
}
}
// final answer
return dp[ 0 ][K];
}
// Driver code
public static void main(String[] args) {
int N = 9 , M = 2 , K = 3 ;
String S = "432387429" ;
int Firstchar = S.charAt( 0 ) - '0' ;
int Lastchar = S.charAt(N - 1 ) - '0' ;
if (Firstchar % 2 != 0 || Lastchar % 2 != 1 ) {
System.out.println( 0 );
} else {
// Function call
System.out.println(SplitString(N, K, M, S));
}
}
} |
# Python 3 program for the above approach # Function to find the possible ways to split def SplitString(N, K, M, s):
dp = [[ - 1 for j in range (K + 1 )] for i in range (N + 1 )]
# Initialize the base cases
for i in range (N + 1 ):
for j in range (K + 1 ):
# If the length of string is N, then no split is possible
if i = = N:
dp[i][j] = 0
elif j = = 1 :
# If K = 1, then only one split is allowed
Remchar = N - i
if Remchar > = M:
# If remaining characters in string >= M,
# then only one split is possible
dp[i][j] = 1
else :
dp[i][j] = 0
else :
dp[i][j] = - 1
# Fill the DP table
for j in range ( 2 , K + 1 ):
for i in range (N):
ans = 0
length = 0
for k in range (i, N - 1 ):
# Incrementing the length of current substring
length + = 1
# Converting current character to integer
CurrentNum = int (s[k])
NextNum = int (s[k + 1 ])
# Checking if the current substring satisfies the given conditions
if length > = M and CurrentNum % 2 = = 1 and NextNum % 2 = = 0 :
# Adding the number of ways to split the remaining
# string after the current substring into j-1 parts
ans + = dp[k + 1 ][j - 1 ]
dp[i][j] = ans
# final answer
return dp[ 0 ][K]
# Driver code if __name__ = = '__main__' :
N = 9
M = 2
K = 3
S = "432387429"
Firstchar = int (S[ 0 ])
Lastchar = int (S[N - 1 ])
if Firstchar % 2 ! = 0 or Lastchar % 2 ! = 1 :
print ( 0 )
else :
# Function call
print (SplitString(N, K, M, S))
|
using System;
class GFG {
static int MAX = 1001;
// DP table
static int [, ] dp = new int [MAX, MAX];
// Function to find the possible ways to split
static int SplitString( int N, int K, int M, string s)
{
// Initialize the base cases
for ( int i = 0; i <= N; i++) {
for ( int j = 0; j <= K; j++) {
// If the length of string is N, then no
// split is possible
if (i == N)
dp[i, j] = 0;
else if (j == 1) {
// If K = 1, then only one split is
// allowed
int Remchar = N - i;
if (Remchar >= M)
// If remaining characters in string
// >= M, then only one split is
// possible
dp[i, j] = 1;
else
dp[i, j] = 0;
}
else {
dp[i, j] = -1;
}
}
}
// Fill the DP table
for ( int j = 2; j <= K; j++) {
for ( int i = 0; i < N; i++) {
int ans = 0;
int length = 0;
for ( int k = i; k < N - 1; k++) {
// Incrementing the length of current
// substring
length++;
// Converting current character to
// integer
int CurrentNum
= ( int )Char.GetNumericValue(s[k]);
int NextNum = ( int )Char.GetNumericValue(
s[k + 1]);
// Checking if the current substring
// satisfies the given conditions
if (length >= M && CurrentNum % 2 == 1
&& NextNum % 2 == 0) {
// Adding the number of ways to
// split the remaining string after
// the current substring into j-1
// parts
ans += dp[k + 1, j - 1];
}
}
dp[i, j] = ans;
}
}
// final answer
return dp[0, K];
}
// Driver code
public static void Main()
{
int N = 9, M = 2, K = 3;
string S = "432387429" ;
int Firstchar = ( int )Char.GetNumericValue(S[0]);
int Lastchar = ( int )Char.GetNumericValue(S[N - 1]);
if (Firstchar % 2 != 0 || Lastchar % 2 != 1) {
Console.WriteLine(0);
}
else {
// Function call
Console.WriteLine(SplitString(N, K, M, S));
}
}
} // This code is contributed by sarojmcy2e |
// JavaScript program for the above approach let dp = []; // Function to find the possible ways to split function SplitString(N, K, M, s) {
// Initialize the base cases for (let i = 0; i <= N; i++) {
dp[i] = new Array(K + 1);
for (let j = 0; j <= K; j++) {
// If the length of string is N, then no split is possible if (i == N)
dp[i][j] = 0; else if (j == 1) {
// If K = 1, then only one split is allowed let Remchar = N - i; if (Remchar >= M)
// If remaining characters in string >= M, // then only one split is possible dp[i][j] = 1; else dp[i][j] = 0; } else {
dp[i][j] = -1; } } } // Fill the DP table for (let j = 2; j <= K; j++) {
for (let i = 0; i < N; i++) {
let ans = 0;
let length = 0;
for (let k = i; k < N - 1; k++) {
// Incrementing the length of current substring
length++;
// Converting current character to integer
let CurrentNum = parseInt(s[k]);
let NextNum = parseInt(s[k + 1]);
// Checking if the current substring satisfies the given conditions
if (length >= M && CurrentNum % 2 == 1 && NextNum % 2 == 0) {
// Adding the number of ways to split the remaining
// string after the current substring into j-1 parts
ans += dp[k + 1][j - 1];
}
}
dp[i][j] = ans;
}
} // final answer return dp[0][K];
} // Driver code let N = 9, M = 2, K = 3; let S = "432387429" ;
let Firstchar = parseInt(S[0]); let Lastchar = parseInt(S[N - 1]); if (Firstchar % 2 != 0 || Lastchar % 2 != 1) {
console.log(0); } else {
// Function call console.log(SplitString(N, K, M, S)); } |
Output:
3
Time Complexity: O(N*K)
Auxiliary Space: O(N*K)