Open In App

Minimize partitions in given string to get another string

Improve
Improve
Like Article
Like
Save
Share
Report

Given two strings A and B, print the minimum number of slices required in A to get another string B. In case, if it is not possible to get B from A, then print  “-1”.

Examples : 

Input:  A = “geeksforgeeks”, B = “ksgek”
Output:  5
Explanation:  g | ee | ks | forge | ek | s : minimum 5 slices are required to create B

Input:  A = “topgames”, B = “mepo”
Output: 5
Explanation:   t | o | p |  ga | me | s  :  minimum 5 slices are required to create B

Input:  A = “memk”, B = “memo”
Output: -1
Explanation: Not possible to create B with the help of A

Approach: This problem is a variation of the Longest Common Substring problem. The main idea to do this problem is to get the longest common substring between A and B and then decide on the basis of the start index of the common substring in A, the number of slices needed to cut that portion from A. Then take out that portion from A with either 1 or 2 slices. Also, remove that substring from B and replace that substring with “0” or anything other than alphabets in the case of A. Now, follow the below steps to solve this problem:

  • First, make a simple check with lengths of A and B. If B is longer, then return -1.
  • Now the first step is to find the longest common substring in both the strings.
  • Now, if the start index or the end index of that common substring in String A is 0 or N (A.length()-1) respectively, then in that only 1 slice is needed to cut that portion out.

For example: A = “game” and B = “ga” then  ga | me. Only one slice is required

  • If the substring is between the first and last character of string A, then in that case, 2 slices are required to cut that portion out.

For example: A = “gamer” and B = “me” ->  ga | me | r . Two slices are required

  • Now, reduce the size of B by removing the current longest substring from it. It is necessary to do this because so that a different substring is chosen as the longest common substring in the next call longestSubstring().
  • After that, replace that common substring present in A with the character “0”. The substring can not be removed directly from A because the order is important as we are using the index of common substring present in A to decide the number of slices.
  • Repeat the same process until the string B becomes empty.

Below is the implementation of the above approach:

C++




// c++ program for the above approach
#include<bits/stdc++.h>
using namespace std;
 
// Function returning the ending points
// of LCS and the length of LCS
int* longestSubString(string X, string Y)
{
 
    // Find length of both the Strings.
    int m = X.size();
    int n = Y.size();
 
    // Variable to store length of
    // longest common subString.
    int result = 0;
 
    // Variable to store ending point of
    // longest common subString in X.
    int endIndexX = 0;
    int endIndexY = 0;
 
    // Matrix to store result of two
    // consecutive rows at a time.
    int cache[2][m+1];
 
    // Variable to represent which row of
    // matrix is current row.
    int currentRow = 0;
 
    // For a particular value of i and j,
    // len[currRow][j] stores length of
    // longest common subString in
    // String X[0..i] and Y[0..j].
    for (int i = 0; i <= m; i++) {
        for (int j = 0; j <= n; j++) {
            if (i == 0 || j == 0) {
                cache[currentRow][j] = 0;
            }
            else if (X[i-1] == Y[j-1]) {
                cache[currentRow][j] = cache[1 - currentRow][j - 1] + 1;
                if (cache[currentRow][j] > result) {
                    result = cache[currentRow][j];
                    endIndexX = i - 1;
                    endIndexY = j - 1;
                }
            }
            else {
                cache[currentRow][j] = 0;
            }
        }
 
        // Make current row as previous row and
        // previous row as new current row.
        currentRow = 1 - currentRow;
    }
 
    // Longest common subString is from index
    // (endIndexX - result + 1) in X and
    // (endIndexY - result + 1) in Y.
    int* x = new int[3];
    x[0] = (endIndexX  - result + 1);
    x[1] = (endIndexY - result + 1);
    x[2] = result;
    return x;
}
 
// Function to replace used substring in A with 0's
string processString(string A,int index,int length)
{
    string X = A.substr(0, index);
    string Y = "";
 
    // Inserting "0" in place
    // of that substring.
    for (int i = 0; i < length; i++) {
        Y += "0";
    }
 
    string Z = A.substr(index + length);
    return (X + Y + Z);
}
 
// Function to return the minimum
// number of slices required.
int minimumSlice(string A,string B)
{
    // Checking the length of A and B.
    if (A.size() < B.size())
        return -1;
 
    // If both are equal no slice required.
    if (A == B)
        return 0;
 
    int result = 0, n = (A.size() - 1);
 
    // Loop continues until B is empty.
    while (B.size() > 0) {
        int* processed = longestSubString(A, B);
        if (processed[2] == 0)
            return -1;
 
        // Incrementing result by 1 if
        // longest substring start at index 0
        // or the end point is equal to n
        if ((processed[0] + processed[2] - 1 == n) || processed[0] == 0) {
 
            // Result should only
            // be incremented if
            // character just before
            // and after the
            // substring is not "0";
            // if "0" is there,
            // then the slice
            // has already been counted
            if (processed[0] == 0) {
                if (A[processed[0] + processed[2]] != '0')
                    result++;
            }
            else {
                if (A[processed[0] - 1] != '0')
                    result++;
            }
        }
 
        // In any other case increment it by 2
        else {
 
            // Result should only
            // be incremented if
            // character just before
            // and after the substring
            // is not "0";
            // if "0" is there,
            // then the slice has
            // already been counted.
            if (A[processed[0] + processed[2]] != '0') {
                result++;
            }
 
            if (A[processed[0] - 1] != '0') {
                result++;
            }
        }
 
        // Reducing the size of B by
        // removing current longest
        // substring from it.
        B = B.substr(0, processed[1]) + B.substr(processed[1] + processed[2]);
 
        // Clearing the used substring from A.
        A = processString(A, processed[0], processed[2]);
    }
    return result;
}
 
int main() {
    cout << minimumSlice("topgames", "mepo");
}
 
// The code is contributed by Nidhi goel.


Java




// Java program for the above approach
import java.io.*;
 
class GFG {
 
    // Function returning the ending points
    // of LCS and the length of LCS
    public static int[] longestSubString(
        String X, String Y)
    {
 
        // Find length of both the Strings.
        int m = X.length();
        int n = Y.length();
 
        // Variable to store length of
        // longest common subString.
        int result = 0;
 
        // Variable to store ending point of
        // longest common subString in X.
        int endIndexX = 0;
        int endIndexY = 0;
 
        // Matrix to store result of two
        // consecutive rows at a time.
        int cache[][] = new int[2][m + 1];
 
        // Variable to represent which row of
        // matrix is current row.
        int currentRow = 0;
 
        // For a particular value of i and j,
        // len[currRow][j] stores length of
        // longest common subString in
        // String X[0..i] and Y[0..j].
        for (int i = 0; i <= m; i++) {
            for (int j = 0; j <= n; j++) {
                if (i == 0 || j == 0) {
                    cache[currentRow][j] = 0;
                }
                else if (X.charAt(i - 1)
                         == Y.charAt(j - 1)) {
                    cache[currentRow][j]
                        = cache[1 -
                                currentRow][j
                                            - 1]
                        + 1;
                    if (cache[currentRow][j]
                        > result) {
                        result
                            = cache[currentRow][j];
                        endIndexX = i - 1;
                        endIndexY = j - 1;
                    }
                }
                else {
                    cache[currentRow][j] = 0;
                }
            }
 
            // Make current row as previous row and
            // previous row as new current row.
            currentRow = 1 - currentRow;
        }
 
        // Longest common subString is from index
        // (endIndexX - result + 1) in X and
        // (endIndexY - result + 1) in Y.
        int[] array = new int[] { (endIndexX
                                   - result
                                   + 1),
                                  (endIndexY
                                   - result
                                   + 1),
                                  result };
        return array;
    }
 
    // Function to replace used substring in A with 0's
    public static String processString(String A,
                                       int index,
                                       int length)
    {
        String X = A.substring(0, index);
        String Y = "";
 
        // Inserting "0" in place
        // of that substring.
        for (int i = 0; i < length; i++) {
            Y += "0";
        }
 
        String Z = A.substring(index
                               + length);
        return (X + Y + Z);
    }
 
    // Function to return the minimum
    // number of slices required.
    public static int minimumSlice(String A,
                                   String B)
    {
        // Checking the length of A and B.
        if (A.length() < B.length())
            return -1;
 
        // If both are equal no slice required.
        if (A.equals(B))
            return 0;
 
        int result = 0, n = (A.length() - 1);
 
        // Loop continues until B is empty.
        while (!B.isEmpty()) {
            int[] processed
                = longestSubString(A, B);
            if (processed[2] == 0)
                return -1;
 
            // Incrementing result by 1 if
            // longest substring start at index 0
            // or the end point is equal to n
            if ((processed[0]
                 + processed[2] - 1 == n)
                || processed[0] == 0) {
 
                // Result should only
                // be incremented if
                // character just before
                // and after the
                // substring is not "0";
                // if "0" is there,
                // then the slice
                // has already been counted
                if (processed[0] == 0) {
                    if (A.charAt(processed[0]
                                 + processed[2])
                        != '0')
                        result++;
                }
                else {
                    if (A.charAt(processed[0] - 1)
                        != '0')
                        result++;
                }
            }
 
            // In any other case increment it by 2
            else {
 
                // Result should only
                // be incremented if
                // character just before
                // and after the substring
                // is not "0";
                // if "0" is there,
                // then the slice has
                // already been counted.
                if (A.charAt(processed[0]
                             + processed[2])
                    != '0') {
                    result++;
                }
 
                if (A.charAt(processed[0] - 1)
                    != '0') {
                    result++;
                }
            }
 
            // Reducing the size of B by
            // removing current longest
            // substring from it.
            B = B.substring(0, processed[1])
                + B.substring(processed[1]
                              + processed[2]);
 
            // Clearing the used substring from A.
            A = processString(A, processed[0],
                              processed[2]);
        }
        return result;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        System.out.println(minimumSlice("topgames", "mepo"));
    }
}


Python3




# Python 3 program for the above approach
 
# Function returning the ending points
# of LCS and the length of LCS
 
 
def longestSubString(
        X,  Y):
 
    # Find length of both the Strings.
    m = len(X)
    n = len(Y)
 
    # Variable to store length of
    # longest common subString.
    result = 0
 
    # Variable to store ending point of
    # longest common subString in X.
    endIndexX = 0
    endIndexY = 0
 
    # Matrix to store result of two
    # consecutive rows at a time.
    cache = [[0 for x in range(m+1)] for y in range(2)]
 
    # Variable to represent which row of
    # matrix is current row.
    currentRow = 0
 
    # For a particular value of i and j,
    # len[currRow][j] stores length of
    # longest common subString in
    # String X[0..i] and Y[0..j].
    for i in range(m + 1):
        for j in range(n + 1):
            if (i == 0 or j == 0):
                cache[currentRow][j] = 0
 
            elif (X[i - 1] == Y[j - 1]):
                cache[currentRow][j] = cache[1 - currentRow][j - 1] + 1
                if (cache[currentRow][j]
                        > result):
                    result = cache[currentRow][j]
                    endIndexX = i - 1
                    endIndexY = j - 1
            else:
                cache[currentRow][j] = 0
 
        # Make current row as previous row and
        # previous row as new current row.
        currentRow = 1 - currentRow
 
    # Longest common subString is from index
    # (endIndexX - result + 1) in X and
    # (endIndexY - result + 1) in Y.
    array = [(endIndexX
              - result
              + 1),
             (endIndexY
              - result
              + 1),
             result]
    return array
 
# Function to replace used substring in A with 0's
 
 
def processString(A, index, length):
 
    X = A[0: index]
    Y = ""
 
    # Inserting "0" in place
    # of that substring.
    for i in range(length):
        Y += "0"
 
    Z = A[index + length:]
    return (X + Y + Z)
 
# Function to return the minimum
# number of slices required.
 
 
def minimumSlice(A,
                 B):
 
    # Checking the length of A and B.
    if (len(A) < len(B)):
        return -1
 
    # If both are equal no slice required.
    if (A == B):
        return 0
 
    result = 0
    n = (len(A) - 1)
 
    # Loop continues until B is empty.
    while (len(B) != 0):
        processed = longestSubString(A, B)
        if (processed[2] == 0):
            return -1
 
        # Incrementing result by 1 if
        # longest substring start at index 0
        # or the end point is equal to n
        if ((processed[0]
             + processed[2] - 1 == n)
                or processed[0] == 0):
 
            # Result should only
            # be incremented if
            # character just before
            # and after the
            # substring is not "0"
            # if "0" is there,
            # then the slice
            # has already been counted
            if (processed[0] == 0):
                if (A[processed[0] + processed[2]] != '0'):
                    result += 1
 
            else:
                if (A[processed[0] - 1] != '0'):
                    result += 1
 
        # In any other case increment it by 2
        else:
 
            # Result should only
            # be incremented if
            # character just before
            # and after the substring
            # is not "0"
            # if "0" is there,
            # then the slice has
            # already been counted.
            if (A[processed[0]
                  + processed[2]]
                    != '0'):
                result += 1
 
            if (A[processed[0] - 1] != '0'):
                result += 1
 
        # Reducing the size of B by
        # removing current longest
        # substring from it.
        B = B[0:processed[1]] + B[processed[1] + processed[2]:]
 
        # Clearing the used substring from A.
        A = processString(A, processed[0],
                          processed[2])
 
    return result
 
# Driver Code
if __name__ == "__main__":
 
    print(minimumSlice("topgames", "mepo"))
 
    # This code is contributed by ukasp.


C#




// C# program for the above approach
 
using System;
class GFG
{
 
    // Function returning the ending points
    // of LCS and the length of LCS
    public static int[] longestSubstring(string X, string Y)
    {
 
        // Find length of both the strings.
        int m = X.Length;
        int n = Y.Length;
 
        // Variable to store length of
        // longest common substring.
        int result = 0;
 
        // Variable to store ending point of
        // longest common substring in X.
        int endIndexX = 0;
        int endIndexY = 0;
 
        // Matrix to store result of two
        // consecutive rows at a time.
        int[,] cache = new int[2, m + 1];
 
        // Variable to represent which row of
        // matrix is current row.
        int currentRow = 0;
 
        // For a particular value of i and j,
        // len[currRow][j] stores length of
        // longest common substring in
        // string X[0..i] and Y[0..j].
        for (int i = 0; i <= m; i++)
        {
            for (int j = 0; j <= n; j++)
            {
                if (i == 0 || j == 0)
                {
                    cache[currentRow, j] = 0;
                }
                else if (X[i - 1] == Y[j - 1])
                {
                    cache[currentRow, j]
                        = cache[1 - currentRow, j - 1]
                        + 1;
                    if (cache[currentRow, j]
                        > result)
                    {
                        result
                            = cache[currentRow, j];
                        endIndexX = i - 1;
                        endIndexY = j - 1;
                    }
                }
                else
                {
                    cache[currentRow, j] = 0;
                }
            }
 
            // Make current row as previous row and
            // previous row as new current row.
            currentRow = 1 - currentRow;
        }
 
        // Longest common substring is from index
        // (endIndexX - result + 1) in X and
        // (endIndexY - result + 1) in Y.
        int[] array = new int[] { (endIndexX
                                   - result
                                   + 1),
                                  (endIndexY
                                   - result
                                   + 1),
                                  result };
        return array;
    }
 
    // Function to replace used substring in A with 0's
    public static string processstring(string A,
                                       int index,
                                       int length)
    {
        string X = A.Substring(0, index);
        string Y = "";
 
        // Inserting "0" in place
        // of that substring.
        for (int i = 0; i < length; i++)
        {
            Y += "0";
        }
 
        string Z = A.Substring(index
                               + length);
        return (X + Y + Z);
    }
 
    // Function to return the minimum
    // number of slices required.
    public static int minimumSlice(string A,
                                   string B)
    {
        // Checking the length of A and B.
        if (A.Length < B.Length)
            return -1;
 
        // If both are equal no slice required.
        if (A.Equals(B))
            return 0;
 
        int result = 0, n = (A.Length - 1);
 
        // Loop continues until B is empty.
        while (B.Length != 0)
        {
            int[] processed
                = longestSubstring(A, B);
            if (processed[2] == 0)
                return -1;
 
            // Incrementing result by 1 if
            // longest substring start at index 0
            // or the end point is equal to n
            if ((processed[0]
                 + processed[2] - 1 == n)
                || processed[0] == 0)
            {
 
                // Result should only
                // be incremented if
                // character just before
                // and after the
                // substring is not "0";
                // if "0" is there,
                // then the slice
                // has already been counted
                if (processed[0] == 0)
                {
                    if (A[processed[0] + processed[2]]
                        != '0')
                        result++;
                }
                else
                {
                    if (A[processed[0] - 1]
                        != '0')
                        result++;
                }
            }
 
            // In any other case increment it by 2
            else
            {
 
                // Result should only
                // be incremented if
                // character just before
                // and after the substring
                // is not "0";
                // if "0" is there,
                // then the slice has
                // already been counted.
                if (A[processed[0] + processed[2]]
                    != '0')
                {
                    result++;
                }
 
                if (A[processed[0] - 1]
                    != '0')
                {
                    result++;
                }
            }
 
            // Reducing the size of B by
            // removing current longest
            // substring from it.
            B = B.Substring(0, processed[1])
                + B.Substring(processed[1]
                              + processed[2]);
 
            // Clearing the used substring from A.
            A = processstring(A, processed[0],
                              processed[2]);
        }
        return result;
    }
 
    // Driver Code
    public static void Main()
    {
        Console.Write(minimumSlice("topgames", "mepo"));
    }
}
 
// This code is contributed by gfgking.


Javascript




// Javascript program for the above approach
 
// Function returning the ending points
// of LCS and the length of LCS
function longestSubString(X, Y) {
 
    // Find length of both the Strings.
    let m = X.length;
    let n = Y.length;
 
    // Variable to store length of
    // longest common subString.
    let result = 0;
 
    // Variable to store ending point of
    // longest common subString in X.
    let endIndexX = 0;
    let endIndexY = 0;
 
    // Matrix to store result of two
    // consecutive rows at a time.
    let cache = new Array(2).fill(0).map(() => new Array(m + 1));
 
    // Variable to represent which row of
    // matrix is current row.
    let currentRow = 0;
 
    // For a particular value of i and j,
    // len[currRow][j] stores length of
    // longest common subString in
    // String X[0..i] and Y[0..j].
    for (let i = 0; i <= m; i++) {
        for (let j = 0; j <= n; j++) {
            if (i == 0 || j == 0) {
                cache[currentRow][j] = 0;
            }
            else if (X.charAt(i - 1)
                == Y.charAt(j - 1)) {
                cache[currentRow][j]
                    = cache[1 -
                    currentRow][j
                    - 1]
                    + 1;
                if (cache[currentRow][j]
                    > result) {
                    result
                        = cache[currentRow][j];
                    endIndexX = i - 1;
                    endIndexY = j - 1;
                }
            }
            else {
                cache[currentRow][j] = 0;
            }
        }
 
        // Make current row as previous row and
        // previous row as new current row.
        currentRow = 1 - currentRow;
    }
 
    // Longest common subString is from index
    // (endIndexX - result + 1) in X and
    // (endIndexY - result + 1) in Y.
    let array = [(endIndexX - result + 1), (endIndexY - result + 1), result];
    return array;
}
 
// Function to replace used substring in A with 0's
function processString(A, index, length) {
    let X = A.substring(0, index);
    let Y = "";
 
    // Inserting "0" in place
    // of that substring.
    for (let i = 0; i < length; i++) {
        Y += "0";
    }
 
    let Z = A.substring(index
        + length);
    return (X + Y + Z);
}
 
// Function to return the minimum
// number of slices required.
function minimumSlice(A, B) {
    // Checking the length of A and B.
    if (A.length < B.length)
        return -1;
 
    // If both are equal no slice required.
    if (A === B)
        return 0;
 
    let result = 0, n = (A.length - 1);
 
    // Loop continues until B is empty.
    while (B.length != 0) {
        let processed = longestSubString(A, B);
        if (processed[2] == 0)
            return -1;
 
        // Incrementing result by 1 if
        // longest substring start at index 0
        // or the end point is equal to n
        if ((processed[0]
            + processed[2] - 1 == n)
            || processed[0] == 0) {
 
            // Result should only
            // be incremented if
            // character just before
            // and after the
            // substring is not "0";
            // if "0" is there,
            // then the slice
            // has already been counted
            if (processed[0] == 0) {
                if (A.charAt(processed[0]
                    + processed[2])
                    != '0')
                    result++;
            }
            else {
                if (A.charAt(processed[0] - 1)
                    != '0')
                    result++;
            }
        }
 
        // In any other case increment it by 2
        else {
 
            // Result should only
            // be incremented if
            // character just before
            // and after the substring
            // is not "0";
            // if "0" is there,
            // then the slice has
            // already been counted.
            if (A.charAt(processed[0]
                + processed[2])
                != '0') {
                result++;
            }
 
            if (A.charAt(processed[0] - 1)
                != '0') {
                result++;
            }
        }
 
        // Reducing the size of B by
        // removing current longest
        // substring from it.
        B = B.substring(0, processed[1])
            + B.substring(processed[1]
                + processed[2]);
 
        // Clearing the used substring from A.
        A = processString(A, processed[0],
            processed[2]);
    }
    return result;
}
 
// Function Call
console.log(minimumSlice("topgames", "mepo"));


Output

5

Time complexity: O(N*(M2)) where N is the length of string A and M is the length of string B
Auxiliary space: O(M)



Last Updated : 02 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads