Given two strings S and T, both of length N and S is an anagram of string T, the task is to convert string S to T by performing the following operations minimum number of times:
- Remove a character from either end.
- Insert a character at any position.
Print the count of the minimum number of operations required.
Examples:
Input: S = “qpmon”, T = “mnopq”
Output: 3
Explanation:
Operation 1: Remove ‘n’ from the end, and insert it at the second last position. The string S modifies to “qpmno”.
Operation 2: Remove ‘q’ from the start, and insert it at the last position. The string S modifies to “pmnoq”.
Operation 3: Remove ‘p’ from the start, and insert it at the second last position. The string S modifies to “mnopq” which is same as the desired string T.Input: S = “abab”, T = “baba”
Output: 1
Approach: The given problem can be solved by the following observation:
- It is required to find the length of the longest substring of A which is a subsequence in B. Let the length of that sub string be L.
- Then, the remaining characters can be inserted without disturbing the existing order.
- To conclude, the optimal answer will be equal to N – L.
Therefore, from the above observations, the minimum number of operations required is the difference between N and the length of the longest substring of the string A which is a subsequence in the string B.
Below is the implementation of the above approach:
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
// Function to find the longest substring // in string A which is a subsequence in B int findLongestSubstring(
int posA, int posB, string& A,
string& B, bool canSkip, int n,
vector<vector<vector< int > > >& dp)
{ // If the indices are out of bounds
if (posA >= n || posB >= n) {
return 0;
}
// If an already computed subproblem occurred
if (dp[posA][posB][canSkip] != -1) {
return dp[posA][posB][canSkip];
}
// Required answer if the all the
// characters of A and B are the same
int op1 = 0;
// Required answer if there is no
// substring A which is a
// subsequence in B
int op2 = 0;
// Required answer if the current
// character in B is skipped
int op3 = 0;
if (A[posA] == B[posB]) {
op1 = 1 + findLongestSubstring(
posA + 1, posB + 1, A,
B, 0, n, dp);
}
if (canSkip) {
op2 = findLongestSubstring(
posA + 1, posB, A, B,
canSkip, n, dp);
}
op3 = findLongestSubstring(
posA, posB + 1, A, B,
canSkip, n, dp);
// The answer for the subproblem is
// the maximum among the three
return dp[posA][posB][canSkip]
= max(op1, max(op2, op3));
} // Function to return the minimum strings // operations required to make two strings equal void minOperations(string A, string B, int N)
{ // Initialize the dp vector
vector<vector<vector< int > > > dp(
N, vector<vector< int > >(
N, vector< int >(2, -1)));
cout << N - findLongestSubstring(
0, 0, A, B, 1, N, dp);
} // Driver Code int main()
{ string A = "abab" ;
string B = "baba" ;
int N = A.size();
minOperations(A, B, N);
return 0;
} |
// Java program for the above approach import java.io.*;
import java.util.*;
class GFG {
// Function to find the longest substring
// in string A which is a subsequence in B
static int
findLongestSubstring( int posA, int posB, String A,
String B, int canSkip, int n,
int dp[][][])
{
// If the indices are out of bounds
if (posA >= n || posB >= n)
{
return 0 ;
}
// If an already computed subproblem occurred
if (dp[posA][posB][canSkip] != - 1 )
{
return dp[posA][posB][canSkip];
}
// Required answer if the all the
// characters of A and B are the same
int op1 = 0 ;
// Required answer if there is no
// substring A which is a
// subsequence in B
int op2 = 0 ;
// Required answer if the current
// character in B is skipped
int op3 = 0 ;
if (A.charAt(posA) == B.charAt(posB))
{
op1 = 1
+ findLongestSubstring(posA + 1 , posB + 1 ,
A, B, 0 , n, dp);
}
if (canSkip == 1 ) {
op2 = findLongestSubstring(posA + 1 , posB, A, B,
canSkip, n, dp);
}
op3 = findLongestSubstring(posA, posB + 1 , A, B,
canSkip, n, dp);
// The answer for the subproblem is
// the maximum among the three
return dp[posA][posB][canSkip]
= Math.max(op1, Math.max(op2, op3));
}
// Function to return the minimum strings
// operations required to make two strings equal
static void minOperations(String A, String B, int N)
{
// Initialize the dp vector
int [][][] dp = new int [N][N][ 2 ];
for ( int i = 0 ; i < N; i++)
{
for ( int j = 0 ; j < N; j++)
{
for ( int k = 0 ; k < 2 ; k++)
{
dp[i][j][k] = - 1 ;
}
}
}
System.out.println(
N - findLongestSubstring( 0 , 0 , A, B, 1 , N, dp));
}
// Driver Code
public static void main(String[] args)
{
String A = "abab" ;
String B = "baba" ;
int N = A.length();
minOperations(A, B, N);
}
} // This code is contributed by Dharanendra L V |
# Python3 program for the above approach # Function to find the longest substring # in A which is a subsequence in B def findLongestSubstring(posA, posB, A, B, canSkip, n):
global dp
if (posA > = n or posB > = n):
return 0
# If an already computed subproblem occurred
if (dp[posA][posB][canSkip] ! = - 1 ):
return dp[posA][posB][canSkip]
# Required answer if the all the
# characters of A and B are the same
op1 = 0
# Required answer if there is no
# subA which is a
# subsequence in B
op2 = 0
# Required answer if the current
# character in B is skipped
op3 = 0
if (A[posA] = = B[posB]):
op1 = 1 + findLongestSubstring(posA + 1 , posB + 1 , A, B, 0 , n)
if (canSkip):
op2 = findLongestSubstring(posA + 1 , posB, A, B, canSkip, n)
op3 = findLongestSubstring(posA, posB + 1 , A, B, canSkip, n)
# The answer for the subproblem is
# the maximum among the three
dp[posA][posB][canSkip] = max (op1, max (op2, op3))
return dp[posA][posB][canSkip]
# Function to return the minimum strings # operations required to make two strings equal def minOperations(A, B, N):
print (N - findLongestSubstring( 0 , 0 , A, B, 1 , N))
# Driver Code if __name__ = = '__main__' :
A = "abab"
B = "baba"
dp = [[[ - 1 , - 1 ] for i in range ( len (A))] for i in range ( len (A))]
N = len (A)
minOperations(A, B, N)
# This code is contributed by mohit kumar 29. |
// C# program for the above approach using System;
class GFG
{ // Function to find the longest substring
// in string A which is a subsequence in B
static int
findLongestSubstring( int posA, int posB, String A,
String B, int canSkip, int n,
int [, , ] dp)
{
// If the indices are out of bounds
if (posA >= n || posB >= n) {
return 0;
}
// If an already computed subproblem occurred
if (dp[posA, posB, canSkip] != -1) {
return dp[posA, posB, canSkip];
}
// Required answer if the all the
// characters of A and B are the same
int op1 = 0;
// Required answer if there is no
// substring A which is a
// subsequence in B
int op2 = 0;
// Required answer if the current
// character in B is skipped
int op3 = 0;
if (A[posA] == B[posB]) {
op1 = 1
+ findLongestSubstring(posA + 1, posB + 1,
A, B, 0, n, dp);
}
if (canSkip == 1) {
op2 = findLongestSubstring(posA + 1, posB, A, B,
canSkip, n, dp);
}
op3 = findLongestSubstring(posA, posB + 1, A, B,
canSkip, n, dp);
// The answer for the subproblem is
// the maximum among the three
return dp[posA, posB, canSkip]
= Math.Max(op1, Math.Max(op2, op3));
}
// Function to return the minimum strings
// operations required to make two strings equal
static void minOperations(String A, String B, int N)
{
// Initialize the dp vector
int [, , ] dp = new int [N, N, 2];
for ( int i = 0; i < N; i++)
{
for ( int j = 0; j < N; j++)
{
for ( int k = 0; k < 2; k++)
{
dp[i, j, k] = -1;
}
}
}
Console.WriteLine(
N - findLongestSubstring(0, 0, A, B, 1, N, dp));
}
// Driver Code
static public void Main ()
{
String A = "abab" ;
String B = "baba" ;
int N = A.Length;
minOperations(A, B, N);
}
} // This code is contributed by Dharanendra L V |
<script> // JavaScript program for the above approach // Function to find the longest substring // in string A which is a subsequence in B function findLongestSubstring( posA, posB, A, B, canSkip, n, dp)
{ // If the indices are out of bounds
if (posA >= n || posB >= n) {
return 0;
}
// If an already computed subproblem occurred
if (dp[posA][posB][canSkip] != -1) {
return dp[posA][posB][canSkip];
}
// Required answer if the all the
// characters of A and B are the same
var op1 = 0;
// Required answer if there is no
// substring A which is a
// subsequence in B
var op2 = 0;
// Required answer if the current
// character in B is skipped
var op3 = 0;
if (A[posA] == B[posB]) {
op1 = 1 + findLongestSubstring(
posA + 1, posB + 1, A,
B, 0, n, dp);
}
if (canSkip) {
op2 = findLongestSubstring(
posA + 1, posB, A, B,
canSkip, n, dp);
}
op3 = findLongestSubstring(
posA, posB + 1, A, B,
canSkip, n, dp);
// The answer for the subproblem is
// the maximum among the three
return dp[posA][posB][canSkip]
= Math.max(op1, Math.max(op2, op3));
} // Function to return the minimum strings // operations required to make two strings equal function minOperations(A, B, N)
{ // Initialize the dp vector
var dp = Array.from(Array(N), ()=> Array(N));
for ( var i =0; i<N; i++)
for ( var j =0; j<N; j++)
dp[i][j] = new Array(2).fill(-1);
document.write( N - findLongestSubstring(
0, 0, A, B, 1, N, dp));
} // Driver Code var A = "abab" ;
var B = "baba" ;
var N = A.length;
minOperations(A, B, N); </script> |
1
Time Complexity: O(N2 )
Space Complexity: O(N2)
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.
Implementation :
// C++ program to find the minimum // operations required to make two // strings equal #include <bits/stdc++.h> using namespace std;
// Function to return the minimum // strings operations required to // make two strings equal void minOperations(string A, string B, int N)
{ // Initialize the dp vector
vector<vector<vector< int >>> dp(
N + 1, vector<vector< int >>(
N + 1, vector< int >(2)));
// Base case initialization
for ( int i = 0; i <= N; i++) {
dp[i][0][0] = 0;
dp[0][i][0] = 0;
dp[i][0][1] = 0;
dp[0][i][1] = 0;
}
// Update the dp table
for ( int i = 1; i <= N; i++) {
for ( int j = 1; j <= N; j++) {
if (A[i - 1] == B[j - 1]) {
dp[i][j][0] = 1 + dp[i - 1][j - 1][0];
}
else {
dp[i][j][0]
= max(dp[i - 1][j][0], dp[i][j - 1][0]);
}
dp[i][j][1]
= max(dp[i - 1][j][1], dp[i][j - 1][1]);
if (A[i - 1] == B[j - 1]) {
dp[i][j][1] = max(dp[i][j][1],
1 + dp[i - 1][j - 1][1]);
}
}
}
// Return the answer
cout << N - max(dp[N][N][0], dp[N][N][1]);
} // Driver code int main()
{ string A = "abab" ;
string B = "baba" ;
int N = A.size();
minOperations(A, B, N);
return 0;
} |
import java.util.Arrays;
public class GFG {
// Function to return the minimum strings operations required to make two strings equal
public static void minOperations(String A, String B, int N) {
// Initialize the dp array
int [][][] dp = new int [N + 1 ][N + 1 ][ 2 ];
// Base case initialization
for ( int i = 0 ; i <= N; i++) {
dp[i][ 0 ][ 0 ] = 0 ;
dp[ 0 ][i][ 0 ] = 0 ;
dp[i][ 0 ][ 1 ] = 0 ;
dp[ 0 ][i][ 1 ] = 0 ;
}
// Update the dp table
for ( int i = 1 ; i <= N; i++) {
for ( int j = 1 ; j <= N; j++) {
if (A.charAt(i - 1 ) == B.charAt(j - 1 )) {
dp[i][j][ 0 ] = 1 + dp[i - 1 ][j - 1 ][ 0 ];
} else {
dp[i][j][ 0 ] = Math.max(dp[i - 1 ][j][ 0 ], dp[i][j - 1 ][ 0 ]);
}
dp[i][j][ 1 ] = Math.max(dp[i - 1 ][j][ 1 ], dp[i][j - 1 ][ 1 ]);
if (A.charAt(i - 1 ) == B.charAt(j - 1 )) {
dp[i][j][ 1 ] = Math.max(dp[i][j][ 1 ], 1 + dp[i - 1 ][j - 1 ][ 1 ]);
}
}
}
// Return the answer
System.out.println(N - Math.max(dp[N][N][ 0 ], dp[N][N][ 1 ]));
}
// Driver code
public static void main(String[] args) {
String A = "abab" ;
String B = "baba" ;
int N = A.length();
minOperations(A, B, N);
}
} |
# Python3 program to find the minimum # operations required to make two # strings equal # Function to return the minimum # strings operations required to # make two strings equal def min_operations(A, B, N):
# Initialize the dp table
dp = [[[ 0 for _ in range ( 2 )] for _ in range (N + 1 )] for _ in range (N + 1 )]
# Update the dp table
for i in range ( 1 , N + 1 ):
for j in range ( 1 , N + 1 ):
if A[i - 1 ] = = B[j - 1 ]:
dp[i][j][ 0 ] = 1 + dp[i - 1 ][j - 1 ][ 0 ]
else :
dp[i][j][ 0 ] = max (dp[i - 1 ][j][ 0 ], dp[i][j - 1 ][ 0 ])
dp[i][j][ 1 ] = max (dp[i - 1 ][j][ 1 ], dp[i][j - 1 ][ 1 ])
if A[i - 1 ] = = B[j - 1 ]:
dp[i][j][ 1 ] = max (dp[i][j][ 1 ], 1 + dp[i - 1 ][j - 1 ][ 1 ])
# Return the answer
return N - max (dp[N][N][ 0 ], dp[N][N][ 1 ])
# Driver code if __name__ = = "__main__" :
A = "abab"
B = "baba"
N = len (A)
result = min_operations(A, B, N)
print (result)
|
using System;
class GFG
{ // Function to return the minimum strings operations required to make two strings equal
static int MinOperations( string A, string B, int N)
{
// Initialize the dp array
int [,,] dp = new int [N + 1, N + 1, 2];
// Base case initialization
for ( int i = 0; i <= N; i++)
{
dp[i, 0, 0] = 0;
dp[0, i, 0] = 0;
dp[i, 0, 1] = 0;
dp[0, i, 1] = 0;
}
// Update the dp table
for ( int i = 1; i <= N; i++)
{
for ( int j = 1; j <= N; j++)
{
if (A[i - 1] == B[j - 1])
{
dp[i, j, 0] = 1 + dp[i - 1, j - 1, 0];
}
else
{
dp[i, j, 0] = Math.Max(dp[i - 1, j, 0], dp[i, j - 1, 0]);
}
dp[i, j, 1] = Math.Max(dp[i - 1, j, 1], dp[i, j - 1, 1]);
if (A[i - 1] == B[j - 1])
{
dp[i, j, 1] = Math.Max(dp[i, j, 1], 1 + dp[i - 1, j - 1, 1]);
}
}
}
// Return the answer
return N - Math.Max(dp[N, N, 0], dp[N, N, 1]);
}
// Driver code
static void Main()
{
string A = "abab" ;
string B = "baba" ;
int N = A.Length;
int result = MinOperations(A, B, N);
Console.WriteLine(result);
}
} |
// Function to find the minimum operations required to make two strings equal function minOperations(A, B, N) {
// Initialize the 3D dp array
let dp = new Array(N + 1);
for (let i = 0; i < N + 1; i++) {
dp[i] = new Array(N + 1);
for (let j = 0; j < N + 1; j++) {
dp[i][j] = [0, 0]; // Initialize as arrays to store two values
}
}
// Base case initialization
for (let i = 0; i <= N; i++) {
dp[i][0][0] = 0;
dp[0][i][0] = 0;
dp[i][0][1] = 0;
dp[0][i][1] = 0;
}
// Update the dp table
for (let i = 1; i <= N; i++) {
for (let j = 1; j <= N; j++) {
if (A[i - 1] === B[j - 1]) {
dp[i][j][0] = 1 + dp[i - 1][j - 1][0];
} else {
dp[i][j][0] = Math.max(dp[i - 1][j][0], dp[i][j - 1][0]);
}
dp[i][j][1] = Math.max(dp[i - 1][j][1], dp[i][j - 1][1]);
if (A[i - 1] === B[j - 1]) {
dp[i][j][1] = Math.max(dp[i][j][1], 1 + dp[i - 1][j - 1][1]);
}
}
}
// Return the answer
return N - Math.max(dp[N][N][0], dp[N][N][1]);
} // Driver code let A = "abab" ;
let B = "baba" ;
let N = A.length; let result = minOperations(A, B, N); console.log(result); |
1
Time Complexity: O(N^2 )
Auxiliary Space: O(N^2)