Transform string A into B by deleting characters from ends and reinserting at any position
Last Updated :
31 Mar, 2023
Given two strings A and B that are anagrams of each other, the task is to convert A to B if possible in minimum number of operations. An operation is defined as removing either the first or the last character in A and inserting it back anywhere in the string.
Examples:
Input: A = "edacb", B = "abcde"
Output : 3
Explanation : The three operations are:
- We can remove "b" and insert it after "a" to get "edabc"
- We can remove "e" and insert it after "c" to get "dabce"
- We can remove "d" and insert it after "c" to get "abcde"
Input : A = "xyz", B = "xyz"
Output : 0
Explanation : String A is equal to String B so no operation is required.
Approach: The approach is based on Dynamic Programming and Longest Common Subsequence (LCS)
Intuition:
- Instead of forming B from A by moving characters from the ends of A to the interior, we will attempt to form A from B by moving characters from B's interior to its ends. It should be evident that the problem is equivalent.
- Now, after doing this reversed operation some number of times, we will have a resulting string B' that we can split into three parts:
B' = prefix + core + suffix
where- core consists of unmoved characters, and
- prefix / suffix are characters that have been moved to the beginning or end, respectively.
- Note that once we have moved a character, it is always suboptimal to move it again.
Since we are free to choose the order in which we move characters, we should choose to move the characters of prefix/suffix from the inside out.
Then, the cost of forming B' from B in this way is len(prefix) + len(suffix). - The core is a subsequence of B : it consists of just the unmoved characters of B, in their original order. Indeed, this works both ways - we can turn any subsequence of B into a core, and arrange the remaining letters arbitrarily around it.
- Now our problem is to find a way to decompose A into those three parts:
- minimizing len(prefix) + len(suffix).
- maximize len(core) (the number of untouched characters).
- This can be restated as finding the maximum-length substring of A which is a subsequence of B.
Algorithm: This problem can be solved with Dynamic Programming much like the classic LCS (longest common subsequence) problem. See the comments in the code for the precise DP state. The main difference from LCS is that we cannot include dp[i-1][j] in dp[i][j], since that would break the contiguity of the A-substring.
Below is the implementation of the above approach :
C++
// C++ implementation of the above approach
#include <bits/stdc++.h>
using namespace std;
// Function to find min operations
int minOperations(string A, string B)
{
// dp[i][j] = length of longest
//(contiguous) suffix of A[0..i]
// that is a subsequence of B[0..j]
int dp[1001][1001];
// r = maximum value over all
// dp[i][j] computed so far
int r = 0;
for (int i = 0; i <= A.size(); ++i) {
for (int j = 0; j <= B.size(); ++j) {
dp[i][j] = 0;
if (i && j) {
// any suffix of A[0..i]
// which is a subsequence of B[0..j]
// is also a subsequence of B[0..j-1]...
dp[i][j] = dp[i][j - 1];
// or, if last character matches (i.e.
// A[i-1] == B[j-1]), and then the rest
// of the suffix is a suffix of
// A[0..i-1] and a subsequence of B[j-1]
if (A[i - 1] == B[j - 1]) {
dp[i][j] = max(
dp[i][j],
1 + dp[i - 1][j - 1]);
r = max(r, dp[i][j]);
}
}
}
}
// r = the length of the
// longest (contiguous) substring
// of A that is a subsequence of B
return A.size() - r;
}
// Driver code
int main()
{
string A = "edacb";
string B = "abcde";
cout << minOperations(A, B);
return 0;
}
Java
// Java implementation of the above approach
import java.util.*;
public class GFG {
// Function to find min operations
static int minOperations(String A, String B)
{
// dp[i][j] = length of longest
//(contiguous) suffix of A[0..i]
// that is a subsequence of B[0..j]
int[][] dp = new int[1001][1001];
// r = maximum value over all
// dp[i][j] computed so far
int r = 0;
for (int i = 0; i <= A.length(); ++i) {
for (int j = 0; j <= B.length(); ++j) {
dp[i][j] = 0;
if (i > 0 && j > 0) {
// any suffix of A[0..i]
// which is a subsequence of B[0..j]
// is also a subsequence of B[0..j-1]...
dp[i][j] = dp[i][j - 1];
// or, if last character matches (i.e.
// A[i-1] == B[j-1]), and then the rest
// of the suffix is a suffix of
// A[0..i-1] and a subsequence of B[j-1]
if (A.charAt(i - 1)
== B.charAt(j - 1)) {
dp[i][j] = Math.max(
dp[i][j], 1 + dp[i - 1][j - 1]);
r = Math.max(r, dp[i][j]);
}
}
}
}
// r = the length of the
// longest (contiguous) substring
// of A that is a subsequence of B
return A.length() - r;
}
// Driver code
public static void main(String args[])
{
String A = "edacb";
String B = "abcde";
System.out.println(minOperations(A, B));
}
}
// This code is contributed by Smim Hossain Mondal.
Python3
<script>
# python3 implementation of the above approach
# Function to find min operations
def minOperations(A, B) :
# dp[i][j] = length of longest
# (contiguous) suffix of A[0..i]
# that is a subsequence of B[0..j]
dp = [[ 0 for _ in range(1001)] for _ in range(1001) ]
# r = maximum value over all
# dp[i][j] computed so far
r = 0
for i in range(0, len(A) + 1) :
for j in range(0, len(B) + 1) :
dp[i][j] = 0
if (i and j) :
# any suffix of A[0..i]
# which is a subsequence of B[0..j]
# is also a subsequence of B[0..j-1]...
dp[i][j] = dp[i][j - 1]
# or, if last character matches (i.e.
# A[i-1] == B[j-1]), and then the rest
# of the suffix is a suffix of
# A[0..i-1] and a subsequence of B[j-1]
if (A[i - 1] == B[j - 1]) :
dp[i][j] = max(
dp[i][j],
1 + dp[i - 1][j - 1])
r = max(r, dp[i][j])
# r = the length of the
# longest (contiguous) substring
# of A that is a subsequence of B
return len(A) - r
# Driver code
if __name__ == "__main__" :
A = "edacb"
B = "abcde"
print(minOperations(A, B))
# This code is contributed by rakeshsahni
C#
// C# implementation of the above approach
using System;
class GFG {
// Function to find min operations
static int minOperations(string A, string B)
{
// dp[i][j] = length of longest
//(contiguous) suffix of A[0..i]
// that is a subsequence of B[0..j]
int[, ] dp = new int[1001, 1001];
// r = maximum value over all
// dp[i][j] computed so far
int r = 0;
for (int i = 0; i <= A.Length; ++i) {
for (int j = 0; j <= B.Length; ++j) {
dp[i, j] = 0;
if (i > 0 && j > 0) {
// any suffix of A[0..i]
// which is a subsequence of B[0..j]
// is also a subsequence of B[0..j-1]...
dp[i, j] = dp[i, j - 1];
// or, if last character matches (i.e.
// A[i-1] == B[j-1]), and then the rest
// of the suffix is a suffix of
// A[0..i-1] and a subsequence of B[j-1]
if (A[i - 1] == B[j - 1]) {
dp[i, j] = Math.Max(
dp[i, j], 1 + dp[i - 1, j - 1]);
r = Math.Max(r, dp[i, j]);
}
}
}
}
// r = the length of the
// longest (contiguous) substring
// of A that is a subsequence of B
return A.Length - r;
}
// Driver code
public static void Main()
{
string A = "edacb";
string B = "abcde";
Console.Write(minOperations(A, B));
}
}
// This code is contributed by ukasp.
JavaScript
<script>
// JavaScript code for the above approach
// Function to find min operations
function minOperations(A, B) {
// dp[i][j] = length of longest
//(contiguous) suffix of A[0..i]
// that is a subsequence of B[0..j]
let dp = new Array(1001);
for (let i = 0; i < dp.length; i++) {
dp[i] = new Array(1001)
}
// r = maximum value over all
// dp[i][j] computed so far
let r = 0;
for (let i = 0; i <= A.length; ++i) {
for (let j = 0; j <= B.length; ++j) {
dp[i][j] = 0;
if (i && j) {
// any suffix of A[0..i]
// which is a subsequence of B[0..j]
// is also a subsequence of B[0..j-1]...
dp[i][j] = dp[i][j - 1];
// or, if last character matches (i.e.
// A[i-1] == B[j-1]), and then the rest
// of the suffix is a suffix of
// A[0..i-1] and a subsequence of B[j-1]
if (A[i - 1] == B[j - 1]) {
dp[i][j] = Math.max(
dp[i][j],
1 + dp[i - 1][j - 1]);
r = Math.max(r, dp[i][j]);
}
}
}
}
// r = the length of the
// longest (contiguous) substring
// of A that is a subsequence of B
return A.length - r;
}
// Driver code
let A = "edacb";
let B = "abcde";
document.write(minOperations(A, B));
// This code is contributed by Potta Lokesh
</script>
Time Complexity : O(N^2)
Auxiliary Space : O(N^2)
Efficient Approach : using array instead of 2d matrix to optimize space complexity
In previous code we can se that dp[i][j] is dependent upon dp[i-1][j-1] or dp[i][j-1] so we can assume that dp[i-1] is previous row and dp[i] is current row
Implementations Steps :
- Initialize an integer array dp of size 1001 with all elements as 0.
- Initialize a variable r to 0.
- Iterate over the characters of string A, and for each character, iterate over the characters of string B.
- For each (i, j) pair of indices, update dp[j] as follows:
a. If A[i] == B[j], then dp[j] = max(dp[j], prev + 1), where prev is the value of dp[j] before the update.
b. Otherwise, dp[j] = 0.
- After updating dp[j], update r as max(r, dp[j])
- The answer is A.size() - r, where A.size() is the length of string A.
- Return the answer.
Implementation :
C++
// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
// Function to find min operations
int minOperations(string A, string B)
{
// dp[j] = length of longest
// (contiguous) suffix of A[0..i]
// that is a subsequence of B[0..j]
int dp[1001] = {0};
// r = maximum value over all
// dp[j] computed so far
int r = 0;
for (int i = 0; i < A.size(); ++i) {
int prev = 0;
for (int j = 0; j < B.size(); ++j) {
int temp = dp[j];
dp[j] = max(dp[j], (A[i] == B[j]) ? prev + 1 : 0);
prev = temp;
r = max(r, dp[j]);
}
}
// r = the length of the
// longest (contiguous) substring
// of A that is a subsequence of B
return A.size() - r;
}
// Driver code
int main()
{
string A = "edacb";
string B = "abcde";
cout << minOperations(A, B);
return 0;
}
//this code is contributed by bhardwajji
Java
// Java program for the above approach
public class Main {
// Function to find min operations
public static int minOperations(String A, String B) {
// dp[j] = length of longest
// (contiguous) suffix of A[0..i]
// that is a subsequence of B[0..j]
int[] dp = new int[1001];
// r = maximum value over all
// dp[j] computed so far
int r = 0;
for (int i = 0; i < A.length(); ++i) {
int prev = 0;
for (int j = 0; j < B.length(); ++j) {
int temp = dp[j];
dp[j] = Math.max(dp[j], (A.charAt(i) == B.charAt(j)) ? prev + 1 : 0);
prev = temp;
r = Math.max(r, dp[j]);
}
}
// r = the length of the
// longest (contiguous) substring
// of A that is a subsequence of B
return A.length() - r;
}
public static void main(String[] args) {
String A = "edacb";
String B = "abcde";
System.out.println(minOperations(A, B));
}
}
Python3
# Python program for the above approach
# Function to find minimum operations
def minOperations(A, B):
# dp[j] = length of longest
# (contiguous) suffix of A[0..i]
# that is a subsequence of B[0..j]
dp = [0] * 1001
# r = maximum value over all
# dp[j] computed so far
r = 0
for i in range(len(A)):
prev = 0
for j in range(len(B)):
temp = dp[j]
dp[j] = max(dp[j], prev + 1 if A[i] == B[j] else 0)
prev = temp
r = max(r, dp[j])
# r = the length of the longest (contiguous) substring
# of A that is a subsequence of B
return len(A) - r
# Driver code
A = "edacb"
B = "abcde"
print(minOperations(A, B))
C#
using System;
class MainClass
{
// Function to find min operations
public static int minOperations(string A, string B)
{
// dp[j] = length of longest
// (contiguous) suffix of A[0..i]
// that is a subsequence of B[0..j]
int[] dp = new int[1001];
// r = maximum value over all
// dp[j] computed so far
int r = 0;
for (int i = 0; i < A.Length; ++i) {
int prev = 0;
for (int j = 0; j < B.Length; ++j) {
int temp = dp[j];
dp[j] = Math.Max(dp[j], (A[i] == B[j]) ? prev + 1 : 0);
prev = temp;
r = Math.Max(r, dp[j]);
}
}
// r = the length of the
// longest (contiguous) substring
// of A that is a subsequence of B
return A.Length - r;
}
public static void Main(string[] args) {
string A = "edacb";
string B = "abcde";
Console.WriteLine(minOperations(A, B));
}
}
JavaScript
// JavaScript program for the above approach
// Function to find min operations
function minOperations(A, B) {
// dp[j] = length of longest
// (contiguous) suffix of A[0..i]
// that is a subsequence of B[0..j]
let dp = new Array(1001).fill(0);
// r = maximum value over all
// dp[j] computed so far
let r = 0;
for (let i = 0; i < A.length; ++i) {
let prev = 0;
for (let j = 0; j < B.length; ++j) {
let temp = dp[j];
dp[j] = Math.max(dp[j], A[i] == B[j] ? prev + 1 : 0);
prev = temp;
r = Math.max(r, dp[j]);
}
}
// r = the length of the
// longest (contiguous) substring
// of A that is a subsequence of B
return A.length - r;
}
// Driver code
let A = "edacb";
let B = "abcde";
console.log(minOperations(A, B));
Time Complexity : O(N^2)
Auxiliary Space : O(N)
Similar Reads
Transform string str1 into str2 by taking characters from string str3
Given three strings str1, str2 & str3. The task is to find whether string str1 can be transformed to string str2 by taking characters from str3. If yes then print âYESâ, Else print âNOâ.Examples: Input: str1 = "abyzf", str2 = "abgdeyzf", str3 = "poqgode". Output: YES Explanation: Remove 'g' from
9 min read
Minimum number of deletions and insertions to transform one string into another
Given two strings s1 and s2. The task is to remove/delete and insert the minimum number of characters from s1 to transform it into s2. It could be possible that the same character needs to be removed/deleted from one point of s1 and inserted at another point.Example 1: Input: s1 = "heap", s2 = "pea"
15+ min read
Minimum operations to transform given string to another by moving characters to front or end
Given two Strings S and T of length N consisting of lowercase alphabets, which are permutations of each other, the task is to print the minimum number of operations to convert S to T. In one operation, pick any character of the string S and move it either to the start or end of the string S. Example
13 min read
Minimum cost to delete characters from String A to remove any subsequence as String B
Given two strings A and B of size N and M respectively, where B is a sub-sequence of A and an array arr[] of size N, where arr[i] is the cost to delete ith character from string A. The task is to find the minimum cost to delete characters from A such that after deletion no subsequence of A is the sa
15+ min read
Count characters to be shifted from the start or end of a string to obtain another string
Given two strings A and B where string A is an anagram of string B. In one operation, remove the first or the last character of the string A and insert at any position in A. The task is to find the minimum number of such operations required to be performed to convert string A into string B. Examples
6 min read
Rearrange string such that characters at same distance from start and end are different
Given a string S of length N, rearrange the characters of the string such that for every index i < N / 2, S[i] != S[N-i-1]. Print -1 if it is impossible to form such a string. Note: If there are multiple possible answers, print any one of them. Examples: Input: S = "aabbcc"Output: "aacbcb"Explana
8 min read
Convert given Strings into T by replacing characters in between strings any number of times
Given an array, arr[] of N strings and a string T of size M, the task is to check if it is possible to make all the strings in the array arr[] same as the string T by removing any character from one string, say arr[i] and inserting it at any position to another string arr[j] any number of times. Exa
9 min read
Insert a character in String at a Given Position
Given a string s, a character c and an integer position pos, the task is to insert the character c into the string s at the specified position pos.Examples: Input: s = "Geeks", c = 'A', pos = 3Output: GeeAksInput: s = "HelloWorld", c = '!', pos = 5Output: Hello!WorldTable of Content[Approach-1] Usin
5 min read
Ways of transforming one string to other by removing 0 or more characters
Given two sequences A, B, find out number of unique ways in sequence A, to form a subsequence of A that is identical to sequence B. Transformation is meant by converting string A (by removing 0 or more characters) to string B. Examples: Input : A = "abcccdf", B = "abccdf" Output : 3 Explanation : Th
7 min read
Check if a string can be transformed to another by sorting substrings
Given two strings str1 and str2, each of length N and consisting of lowercase English alphabets only, the task is to check if string str1 can be transformed to string str2 by performing the following operations any number of times. Choose a non-empty substring in str1 and sort it in-place lexicograp
7 min read