Minimize removal or insertions required to make two strings equal - GeeksforGeeks

14 Jun, 2021
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: 3Explanation: 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++
Java
Python3
C#
Javascript
// 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 Bint 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 equalvoid 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 Codeint main(){    string A = "abab";    string B = "baba";     int N = A.size();     minOperations(A, B, N);     return 0;}
// Java program for the above approachimport 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 Bdef 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 equaldef minOperations(A, B, N):    print(N - findLongestSubstring(0, 0, A, B, 1, N)) # Driver Codeif __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 approachusing 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 Bfunction 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 equalfunction 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 Codevar A = "abab";var B = "baba";var N = A.length;minOperations(A, B, N);  </script>
1
 
Time Complexity: O(N2 )Space Complexity: O(N2)
mohit kumar 29
dharanendralv23
noob2000
subsequence
substring
Dynamic Programming
Pattern Searching
Strings
Strings
Dynamic Programming
Pattern Searching
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Optimal Substructure Property in Dynamic Programming | DP-2
Min Cost Path | DP-6
Maximum Subarray Sum using Divide and Conquer algorithm
Optimal Binary Search Tree | DP-24
Greedy approach vs Dynamic programming
KMP Algorithm for Pattern Searching
Rabin-Karp Algorithm for Pattern Searching
Naive algorithm for Pattern Searching
Boyer Moore Algorithm for Pattern Searching
Check if a string is substring of another