Minimize partitions in given string to get another string
Last Updated :
02 Mar, 2023
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"));
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)
Similar Reads
Minimize the String length by removing given consecutive pairs Given a string S of size N consisting of characters from '0'to '9', the task is to minimize the length of the string where In each minimizing operation, we can remove any two consecutive characters if they are of the form {"12", "21", "34", "43", "56", "65", "78", "87", "09", "90"}. Examples: Input:
7 min read
Find the minimum cost of partitioning the given string S into contiguous substrings Given a string S and an array of strings arr[]. The task is to find the minimum cost of partitioning the given string S into continuous substrings. If a substring is present in arr[] then the cost of partition would be 0, otherwise, the cost would be the length of that substring. Examples: Input: S
7 min read
Minimize operations to make one string contain only characters from other string Given two strings S1 and S2 containing only lower case English alphabets, the task is to minimize the number of operations required to make S1 contain only characters from S2 where in each operation any character of S1 can be converted to any other letter and the cost of the operation will be differ
9 min read
Minimize length of prefix of string S containing all characters of another string T Given two string S and T, the task is to find the minimum length prefix from S which consists of all characters of string T. If S does not contain all characters of string T, print -1. Examples: Input: S = "MarvoloGaunt", T = "Tom" Output: 12 Explanation: The 12 length prefix "MarvoloGaunt" contains
7 min read
Minimum length of string having all permutation of given string. Given a string S where 1\leq length\; of\; S\leq 26 . Assume that all the characters in S are unique. The task is to compute the minimum length of a string which consists of all the permutations of the given string in any order. Note: All permutations must be present as a substring in the resulting
4 min read
Minimizing Operations to Rewrite a String Given a string S, you have to write the same given string using two operations, the task is to find the minimum number of operations to write it. You can only write a sequence of the same character each time.You can choose any substring and overwrite the existing characters with single new character
7 min read
Create lexicographically minimum String using given operation Given a string s of length N consisting of digits from 0 to 9. Find the lexicographically minimum sequence that can be obtained from given string s by performing the given operations: Selecting any position i in the string and delete the digit 'd' at ith position, Insert min(d+1, 9) on any position
7 min read
Minimize cost to convert given string into concatenation of equal substrings of length K Given a string S of length N consisting of lowercase letters and an integer K, where N % K = 0, the task is to find the minimum cost to convert the given string into a concatenated string of the same K-length substrings by performing the following operations: A character can be replaced with another
8 min read
Minimize replacements to make any two of the three given strings equal Given three strings A, B, and C of equal length, the task is to find the minimum number of replacement operations that can be performed such that any two out of the three strings become equal. Examples: Input: A = "aaa", B = "bab", C = "bbb" Output: 1 Explanation: To make the strings B and C equal,
10 min read
Minimum rotations required to get the same String | Set-2 Given a string, we need to find the minimum number of rotations required to get the same string. In this case, we will only consider Left rotations. Examples: Input : s = "geeks" Output : 5 Input : s = "aaaa" Output :1 Naive approach: The basic approach is to keep rotating the string from the first
10 min read