Count ways to Split String into K Substrings Starting with Even Digit and Min Length M


In this problem, we will count ways to partition the given string into the K substrings such that it follows the condition given in the problem statement.

We will use the recursion to solve the problem. Also, we will use the tabular dynamic programming approach to solve the problem efficiently.

Problem statement − We have given a string named bin_Str of a particular length. The string contains only numeric digits from ‘0’ to ‘9’. We need to count the number of ways to partition the string in K substrings such that it follows the below condition.

  • The substring should contain a minimum of 2 characters.

  • The first character of each substring should be an even digit, and the last character should be an odd digit.

Sample examples

Input

M = 2, K = 2; bin_str = "255687"

Output

1

Explanation − We can make 255 | 687 only a partition of the given string according to the conditions of the problem statement.

Input

M = 2, K = 2; bin_str = "26862";

Output

0

Explanation − As the string contains only even digits, we can’t break into the 2 substrings such that each substring end with an odd digit.

Input

M = 2, K = 3; bin_str = "856549867";

Output

3

Explanation − The possible ways of the partitions are 85|65|49867, 8565|49|867, and 85|6549|867.

Approach 1

We will use the recursive function to solve the problem in this approach. If we find the valid substring at the current index, we make the recursive call to count a number of ways to divide the remaining substring into the K − 1 substrings.

Algorithm

Step 1 − Take the first and last characters of the given string.

Step 2 − If the first character is not even and the last character is not odd, return 0.

Step 3 − If the starting index is equal to the string length, return 0 as we reach the end of the given string.

Step 4 − If K == 1, take the difference between the string length and starting index. If it is equal to greater than M, return 1. Otherwise, return 0. Here, we need to get the remaining substring if K is 1.

Step 5 − Initialize the ‘ops’ with ‘0’ to store the count of partition ways and ‘len’ with ‘0’ to store the length of the current substring.

Step 6 − Start traversing the string from the ‘start’ index to the end of the string.

Step 7 − Increment the ‘len’ by 1. Also, take the current and next characters.

Step 8 − If ‘len’ is greater than M, the current digit is odd, and the next digit is even, we can end the partition at the current index. So, make the recursive call of the countWays() function by passing the next index and K – 1 as a function parameter.

Step 9 − At last, return the ‘ops’ value.

Example

#include <bits/stdc++.h>
using namespace std;

int countWays(int start, int str_len, int K, int M, string bin_str) {
    // Geeting first and last character of the substring
    int f_char = bin_str[0] - '0';
    int l_char = bin_str[str_len - 1] - '0';
    if (f_char % 2 != 0 || l_char % 2 != 1) {
        return 0;
    }
    // When we reach at the end
    if (start == str_len)
        return 0;
    // Base case
    if (K == 1) {
        int chars = str_len - start;
        // Validate minimum length of substring
        if (chars >= M)
            return 1;
        return 0;
    }    
    int ops = 0;
    int len = 0;
    // Traverse all partions
    for (int p = start; p < str_len - 1; p++) {
        len++;
        int first = bin_str[p] - '0';
        int second = bin_str[p + 1] - '0';
        // If we can end the partition at p and start a new partition at p+1
        if (len >= M && first % 2 == 1) {
            if (second % 2 == 0) {
                ops += countWays(p + 1, str_len, K - 1, M, bin_str);
            }
        }
    }
    return ops;
}
int main() {
    int M = 2, K = 2;
    string bin_str = "255687";
    int str_len = bin_str.length();
    cout << "The number of ways to split the string is " << countWays(0, str_len, K, M, bin_str) << endl;
    return 0;
}

Output

The number of ways to split the string is 1

The number of ways to split the string is 1

Space complexity − O(1), as we don’t use extra space.

Approach 2

In this approach, we will use the tabular dynamic programming technique to count the number of ways to split the string in K partitions. We will use the matrix to store the output of the previous state.

Algorithm

Step 1 − Define the global matrix[] array of size 1001 x 1001. A matrix row is mapped to a string character, and a matrix column is mapped to K.

Step 2 − Take the first and last character of the string. If the first character is even and the last character is odd, execute the countWays() function. Otherwise, print 0 in the output.

Step 3 − In the countWays function, Initilaize the matrix[] array.

Step 4 − Traverse the matrix rows equal to the string length and column equal to K. If the row equals the string length, update the whole row with 0.

Step 5 − Else, if q is 1, and string length − current index is greater than M, initialize the array matrix[p][q] with 1. Otherwise, initialize the matrix[p][q] with 0.

Step 6 − In other cases, initialize the matrix[p][q] with −1.

Step 7 − Use two nested loops to fill the matrix. Make 2 to K traversal using the outer loop and 0 to string length using the nested loop.

Step 8 − Initialize the ‘ops’ and ‘len’ with 0. Furthermore, start traversing the string from the pth index, and increment the ‘len’ by 1 in each iteration.

Step 9 − Take the current and next character of the string.

Step 10 − If length is greater than M, the current character is odd, and the next character is even, add matrix[k + 1][q − 1] to the ‘ops’.

Step 11 − Update the matrix[p][q] with ‘ops’.

Step 12 − Return matrix[0][k] at last.

Example

#include <bits/stdc++.h>
using namespace std;

int matrix[1001][1001];
int countWays(int str_len, int K, int M, string bin_str) {
    // Base case
    for (int p = 0; p <= str_len; p++) {
        for (int q = 0; q <= K; q++) {
            // When index points to end index of string
            if (p == str_len)
                matrix[p][q] = 0;
            else if (q == 1) {
                // When only 1 split needs to be done
                int chars = str_len - p;
                // Validating substring's minimum len
                if (chars >= M)
                    matrix[p][q] = 1;
                else
                    matrix[p][q] = 0;
            } else {
                // For other cases
                matrix[p][q] = -1;
            }
        }
    }
    // Dynamic programming approach
    for (int q = 2; q <= K; q++) {
        for (int p = 0; p < str_len; p++) {
            int ops = 0;
            int len = 0; // length of current substring
            for (int k = p; k < str_len - 1; k++) {
                len++;
                int first = bin_str[k] - '0';
                int second = bin_str[k + 1] - '0';
                // Validate condition for split
                if (len >= M && first % 2 == 1 && second % 2 == 0) {
                    // Substring starting from k + 1 index needs to be splited in q-1 parts
                    ops += matrix[k + 1][q - 1];
                }
            }
            matrix[p][q] = ops;
        }
    }
    return matrix[0][K];
}
int main() {
    int M = 2, K = 2;
    string bin_str = "255687";
    int str_len = bin_str.length();
    int f_char = bin_str[0] - '0';
    int l_char = bin_str[str_len - 1] - '0';
    cout << "The number of ways to split the string is ";
    if (f_char % 2 != 0 || l_char % 2 != 1) {
        cout << 0 << endl;
    } else {
        cout << countWays(str_len, K, M, bin_str) << endl;
    }
    return 0;
}

Output

The number of ways to split the string is 1

Time complexity − O(N*N*K), where O(N*N) is for finding all substrings, and O(K) is for K partitions.

Space complexity − O(N*K) to use the matrix[] array.

Updated on: 17-Jul-2023

111 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements