Minimize Partitions in given String to get Another String


In this problem, we need to construct one string by slicing the other string. We can use the longest common substring to solve the problem. We can find the longest common substring between both strings, slice str1 into 1 or 2 parts, and remove the substring from str2. Again, we find the longest common substring in updated strings and follow it until str2 becomes empty. In this way, we can solve the problem.

Problem statement – We have given str1 and str2 strings of different lengths. We need to construct the string str2 by slicing and concatenating the parts of str1. We need to find the minimum number of slicing we require with str1 to get the str2 string. If it is not possible to construct the str2 string, print ‘1’.

Sample examples

Input

str1 = "tutorialspoint"; str2 = "intpotu";

Output

3

Explanation – As shown below, we need to slice str1 3 times into the 4 parts.

Tu | torials | po | int

Input

str1 = "tutorialspoint"; str2 = "intpotu";

Output

-1

Explanation – As we can’t construct the str2 from the str1. So, it prints ‘-1’.

Input

str1 = "Welcome"; str2 = "meWe";

Output

2

Explanation – We | lco | me

Approach 1

In this approach, we will find the longest common substrings between given strings, slice the string, and remove the substring from both strings. Also, we will update both strings in each iteration and make iterations until the str2 string becomes empty.

Also, we need to focus on slicing the starting and ending parts, as we need only 1 slice in such cases. Furthermore, we update the character str1 to ‘0’ if the character is already counted in the substring.

Algorithm

Step 1 – If the size of the str1 is less than str2, return -1 as it is not possible to construct the str2 from the str1. If both strings are the same, return 0.

Step 2 – Initialize the ‘answer’ with 0 to store the total number of slices of str1.

Step 3 – Use the while loop to make iterations until the size of the str2 is greater than zero.

Step 4 – Execute the longCommonSubStr() function to get the longest common substring in str1 and str2.

Step 4.1 – In the longCommonSubStr() function, initialize the ‘maxLen’ variable with 0 to store the maximum length, ‘endingStr1’ and ‘endingStr2’ with 0 to store the ending index of the substring in the str1 and str2. Also, initialize the ‘mat’ to store the previous results as we use the dynamic programming approach to find the longest common substring and ‘currentRow’ with 0.

Step 4.2 – Start filling the 2D matrix.

Step 4.3 – If p and q are 0, store the zero at mat[currentRow][q].

Step 4.4 – If characters at (p-1) index in str1 and (q – 1) index in str2 is the same, update the value of mat[currentRow][q] by adding to the previous diagonal entry.

Step 4.5 – If the updated value is greater than the maxLen variable’s value, update the value of the ‘maxLen’, ‘endingStr1’, and ‘endingStr2’ variables.

Step 4.6 – Else, assign 0 to mat[currentRow][q] = 0, as we need to start a new substring.

Step 4.7 – When iterations of the nested loop are completed, update the value of the ‘currentRow’ variable.

Step 4.8 – Create the ‘temp’ array to store the longest common substring length, ending index in str1 and str2. At last, return the ‘temp’ array.

Step 5 – In the getMinSlices() function, it length of the longest common substring is 0, return -1.

Step 6 - If the starting index of the substring is 0, increment the ‘answer’ value by 1 if the next character nearest to the substring is not ‘0’ in str1. If the ending index equals the ‘len – 1’, increment the ‘answer’ value by 1 if the character before the substring is not ‘0’. If it is ‘0’, the part is already sliced, so we don’t need to increment the ‘answer’ value.

Step 7 – If we need to slice the string from the middle, increment the ‘answer’ value accordingly if the character before and after the substring is not equal to ‘0’.

Step 8 – Remove the common substring from the str2 using the substr() method.

Step 9 – Update the str1 string by executing the replaceSubStr() function, which replaces all the substring characters to ‘0’.

Step 9.1 – In the replaceSubStr() function, take the initial substring from the string using the substr() method. After that, create a mid string containing the total zeros equal to the substring length, and get the ending substring.

Step 9.2 – Return the string after concatenating the initial, mid, and end strings.

Step 10 – Return the ‘answer’ value.

Example

#include <bits/stdc++.h>
using namespace std;
int *longCommonSubStr(string str1, string str2) {
    // String sizes
    int len1 = str1.size();
    int len2 = str2.size();
    // To store the maximum length of the common substring.
    int maxLen = 0;
    // For storing the ending index of the substring.
    int endingStr1 = 0;
    int endingStr2 = 0;
    // 2D array to store max len of consecutive rows
    int mat[2][len1 + 1];
    // Pointer to the row
    int currentRow = 0;
    // Finding the longest common substring
    for (int p = 0; p <= len1; p++) {
        for (int q = 0; q <= len2; q++) {
            if (p == 0 || q == 0) {
                mat[currentRow][q] = 0;
            } else if (str1[p - 1] == str2[q - 1]) {
                mat[currentRow][q] = mat[1 - currentRow][q - 1] + 1;
                // If we get longer substring, update values.
                if (mat[currentRow][q] > maxLen) {
                    maxLen = mat[currentRow][q];
                    endingStr1 = p - 1;
                    endingStr2 = q - 1;
                }
            } else {
                mat[currentRow][q] = 0;
            }
        }
        // Change the current row
        currentRow = 1 - currentRow;
    }
    // Storing the starting index of longest common substring
    int *temp = new int[3];
    temp[0] = (endingStr1 - maxLen + 1);
    temp[1] = (endingStr2 - maxLen + 1);
    temp[2] = maxLen;
    return temp;
}
string replaceSubStr(string str1, int ind, int sub_len) {
    // Get initial string
    string start = str1.substr(0, ind);
    string mid = "";
    // Create string with all 0's
    for (int p = 0; p < sub_len; p++) {
        mid += "0";
    }
    // Get remaining string
    string end = str1.substr(ind + sub_len);
    // Return final string
    return (start + mid + end);
}
int getMinSlices(string str1, string str2) {
    // Return -1 if length of str2 is greater
    if (str1.size() < str2.size())
        return -1;
    // Handle the case when both strings are equal.
    if (str1 == str2)
        return 0;
    int answer = 0, len1 = (str1.size() - 1);
    // Find longest common substring of str1 and str2, until str2 is empty.
    while (str2.size() > 0) {
       int *lcs = longCommonSubStr(str1, str2);
        // If the length of the substring is 0, return -1
        if (lcs[2] == 0)
            return -1;

        // Handling the case when starting point is 0, or the ending point is len1
        if ((lcs[0] + lcs[2] - 1 == len1) || lcs[0] == 0) {
            // If the startind index is 0, and the last character is not '0', we need to slice. Otherwise, it's already sliced.
            if (lcs[0] == 0) {
                if (str1[lcs[0] + lcs[2]] != '0')
                    answer++;
            } else {
                // If the ending index is len1, the previous character of the substring's first character is '0', last part of the string is already sliced.
                if (str1[lcs[0] - 1] != '0')
                    answer++;
            }
        }
        // When the substring is between the last and ending character
        else {
            // Increment answer value if strings are not sliced already.
            if (str1[lcs[0] + lcs[2]] != '0') {
                answer++;
            } 
            if (str1[lcs[0] - 1] != '0') {
                answer++;
            }
        }
        // Remove lcs from str2.
        str2 = str2.substr(0, lcs[1]) + str2.substr(lcs[1] + lcs[2]);
        // Pleace '0' in str1 at the place of lcs
        str1 = replaceSubStr(str1, lcs[0], lcs[2]);
    }
    // final output
    return answer;
}
int main() {
    string str1 = "tutorialspoint";
    string str2 = "intpotu";
    cout << "The minimum slices of string str1 is required to construct a string str2 is " << getMinSlices(str1, str2) << endl;
}

Output

The minimum slices of string str1 is required to construct a string str2 is 3

Time complexity – O(N*M*M), as O(N*M) to find the longest common substring, and O(M) to decrease the str2.

Space complexity – O(N), where O(N) to store the dynamic programming results.

Updated on: 25-Aug-2023

48 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements