Count ways to split string into K Substrings starting with even digit and min length M
Last Updated :
04 Apr, 2023
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|429
Input: 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 ith index
- 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++
#include <bits/stdc++.h>
using namespace std;
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;
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;
}
int main()
{
int N = 9, M = 2, K = 3;
string S = "432387429" ;
cout << SplitString(0, N, K, M, S) << endl;
return 0;
}
|
Java
import java.util.*;
class GFG
{
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 ;
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;
}
public static void main(String[] args)
{
int N = 9 , M = 2 , K = 3 ;
String S = "432387429" ;
System.out.println(SplitString( 0 , N, K, M, S));
}
}
|
Python3
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
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"
print (SplitString( 0 , N, K, M, S))
|
C#
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;
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" ;
Console.WriteLine(SplitString(0, N, K, M, S));
}
}
|
Javascript
<script>
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;
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;
}
let N = 9, M = 2, K = 3;
let S = "432387429" ;
document.write(SplitString(0, N, K, M, S));
</script>
|
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++
#include <bits/stdc++.h>
using namespace std;
int dp[1001][1001];
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;
}
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 {
cout << SplitString(0, N, K, M, S) << endl;
}
return 0;
}
|
Java
import java.io.*;
import java.util.*;
public class GFG {
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;
}
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 {
System.out.println(SplitString( 0 , N, K, M, S));
}
}
}
|
Python3
class GFG :
@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]
@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 :
print (GFG.SplitString( 0 , N, K, M, S))
if __name__ = = "__main__" :
GFG.main([])
|
C#
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;
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];
for ( int i = 0; i < 1001; i++)
for ( int j = 0; j < 1001; j++)
dp[i, j] = -1;
Console.WriteLine(SplitString(0, N, K, M, S, dp));
}
}
|
Javascript
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;
}
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 {
console.log(SplitString(0, N, K, M, S,dp));
}
|
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++
#include <bits/stdc++.h>
using namespace std;
int dp[1001][1001];
int SplitString( int N, int K, int M, string& s)
{
for ( int i = 0; i <= N; i++) {
for ( int j = 0; j <= K; j++) {
if (i == N)
dp[i][j] = 0;
else if (j == 1) {
int Remchar = N - i;
if (Remchar >= M)
dp[i][j] = 1;
else
dp[i][j] = 0;
} else {
dp[i][j] = -1;
}
}
}
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++) {
length++;
int CurrentNum = s[k] - '0' ;
int NextNum = s[k + 1] - '0' ;
if (length >= M && CurrentNum % 2 == 1 && NextNum % 2 == 0) {
ans += dp[k + 1][j - 1];
}
}
dp[i][j] = ans;
}
}
return dp[0][K];
}
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 {
cout << SplitString(N, K, M, S) << endl;
}
return 0;
}
|
Java
import java.util.*;
public class Main {
static int [][] dp = new int [ 1001 ][ 1001 ];
static int SplitString( int N, int K, int M, String s) {
for ( int i = 0 ; i <= N; i++) {
for ( int j = 0 ; j <= K; j++) {
if (i == N)
dp[i][j] = 0 ;
else if (j == 1 ) {
int Remchar = N - i;
if (Remchar >= M)
dp[i][j] = 1 ;
else
dp[i][j] = 0 ;
} else {
dp[i][j] = - 1 ;
}
}
}
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++) {
length++;
int CurrentNum = s.charAt(k) - '0' ;
int NextNum = s.charAt(k + 1 ) - '0' ;
if (length >= M && CurrentNum % 2 == 1 && NextNum % 2 == 0 ) {
ans += dp[k + 1 ][j - 1 ];
}
}
dp[i][j] = ans;
}
}
return dp[ 0 ][K];
}
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 {
System.out.println(SplitString(N, K, M, S));
}
}
}
|
Python3
def SplitString(N, K, M, s):
dp = [[ - 1 for j in range (K + 1 )] for i in range (N + 1 )]
for i in range (N + 1 ):
for j in range (K + 1 ):
if i = = N:
dp[i][j] = 0
elif j = = 1 :
Remchar = N - i
if Remchar > = M:
dp[i][j] = 1
else :
dp[i][j] = 0
else :
dp[i][j] = - 1
for j in range ( 2 , K + 1 ):
for i in range (N):
ans = 0
length = 0
for k in range (i, N - 1 ):
length + = 1
CurrentNum = int (s[k])
NextNum = int (s[k + 1 ])
if length > = M and CurrentNum % 2 = = 1 and NextNum % 2 = = 0 :
ans + = dp[k + 1 ][j - 1 ]
dp[i][j] = ans
return dp[ 0 ][K]
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 :
print (SplitString(N, K, M, S))
|
C#
using System;
class GFG {
static int MAX = 1001;
static int [, ] dp = new int [MAX, MAX];
static int SplitString( int N, int K, int M, string s)
{
for ( int i = 0; i <= N; i++) {
for ( int j = 0; j <= K; j++) {
if (i == N)
dp[i, j] = 0;
else if (j == 1) {
int Remchar = N - i;
if (Remchar >= M)
dp[i, j] = 1;
else
dp[i, j] = 0;
}
else {
dp[i, j] = -1;
}
}
}
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++) {
length++;
int CurrentNum
= ( int )Char.GetNumericValue(s[k]);
int NextNum = ( int )Char.GetNumericValue(
s[k + 1]);
if (length >= M && CurrentNum % 2 == 1
&& NextNum % 2 == 0) {
ans += dp[k + 1, j - 1];
}
}
dp[i, j] = ans;
}
}
return dp[0, K];
}
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 {
Console.WriteLine(SplitString(N, K, M, S));
}
}
}
|
Javascript
let dp = [];
function SplitString(N, K, M, s) {
for (let i = 0; i <= N; i++) {
dp[i] = new Array(K + 1);
for (let j = 0; j <= K; j++) {
if (i == N)
dp[i][j] = 0;
else if (j == 1) {
let Remchar = N - i;
if (Remchar >= M)
dp[i][j] = 1;
else
dp[i][j] = 0;
} else {
dp[i][j] = -1;
}
}
}
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++) {
length++;
let CurrentNum = parseInt(s[k]);
let NextNum = parseInt(s[k + 1]);
if (length >= M && CurrentNum % 2 == 1 && NextNum % 2 == 0) {
ans += dp[k + 1][j - 1];
}
}
dp[i][j] = ans;
}
}
return dp[0][K];
}
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 {
console.log(SplitString(N, K, M, S));
}
|
Output:
3
Time Complexity: O(N*K)
Auxiliary Space: O(N*K)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...