Open In App

Minimum number of deletions and insertions to transform one string into another

Last Updated : 16 Nov, 2024
Summarize
Comments
Improve
Suggest changes
Like Article
Like
Save
Share
Report
News Follow

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”
Output: 3
Explanation: Minimum Deletion = 2 and Minimum Insertion = 1
p and h are deleted from the heap, and then p is inserted at the beginning. One thing to note, though p was required it was removed/deleted first from its position and then it was inserted into some other position. Thus, p contributes one to the deletion count and one to the insertion count.

Input: s1 = “geeksforgeeks”, s2 = “geeks”
Output: 8
Explanation: 8 deletions, i.e. remove all characters of the string “forgeeks”.

Using Recursion – O(2^n) Time and O(n) Space

A simple approach to solve the problem involves generating all subsequences of s1 and, for each subsequence, calculating the minimum deletions and insertions required to transform it into s2. An efficent approach uses the concept of longest common subsequence (LCS) to find length of longest LCS. Once we have LCS of two strings, we can find Minimum Insertion and Deletions to convert s1 into s2.

  • To minimize deletions, we only need to remove characters from s1 that are not part of the longest common subsequence (LCS) with s2. This can be determined by subtracting the LCS length from the length of s1. Thus, the minimum number of deletions is:
    minDeletions = length of s1 – LCS length.
  • Similarly, to minimize insertions, we only need to insert characters from s2 into s1 that are not part of the LCS. This can be determined by subtracting the LCS length from the length of s2. Thus, the minimum number of insertions is:
    minInsertions = length of s2 – LCS length.
C++
// C++ program to find the minimum number of insertion and deletion
// using recursion.

#include <iostream>
using namespace std;

int lcs(string &s1, string &s2, int m, int n) {
  
    // Base case: If either string is empty,
    // the LCS length is 0
    if (m == 0 || n == 0)
        return 0;

    // If the last characters of both substrings match
    if (s1[m - 1] == s2[n - 1])
        // Include the matching character in LCS and 
       // recurse for remaining substrings
        return 1 + lcs(s1, s2, m - 1, n - 1);

    else
        // If the last characters do not match, 
      // find the maximum LCS length by:
        // 1. Excluding the last character of s1
        // 2. Excluding the last character of s2
        return max(lcs(s1, s2, m, n - 1), lcs(s1, s2, m - 1, n));
}

int minOperations(string s1, string s2) {
    int m = s1.size();
    int n = s2.size();

    // the length of the LCS for s1[0..m-1]
  // and s2[0..n-1]
    int len = lcs(s1, s2, m, n);

    // Characters to delete from s1
    int minDeletions = m - len;

    // Characters to insert into s1
    int minInsertions = n - len;

    // Total operations needed
    int total = minDeletions + minInsertions;
    return total;
}

int main() {
    string s1 = "AGGTAB";
    string s2 = "GXTXAYB";
    int res = minOperations(s1, s2);
    cout << res;
    return 0;
}
Java
// Java program to find the minimum number of insertions and
// deletions using recursion.

class GfG {
  
    static int lcs(String s1, String s2, int m, int n) {
      
        // Base case: If either string is empty, the LCS
        // length is 0
        if (m == 0 || n == 0) {
            return 0;
        }

        // If the last characters of both substrings match
        if (s1.charAt(m - 1) == s2.charAt(n - 1)) {

            // Include the matching character in LCS
            // and recurse for remaining substrings
            return 1 + lcs(s1, s2, m - 1, n - 1);
        }
        else {
          
            // If the last characters do not match,
            // find the maximum LCS length by:
            // 1. Excluding the last character of s1
            // 2. Excluding the last character of s2
            return Math.max(lcs(s1, s2, m, n - 1),
                            lcs(s1, s2, m - 1, n));
        }
    }

    static int minOperations(String s1, String s2) {
        int m = s1.length();
        int n = s2.length();

        // the length of LCS for s1[0..m-1] and
        //  s2[0..n-1]
        int len = lcs(s1, s2, m, n);

        // Characters to delete from s1
        int minDeletions = m - len;

        // Characters to insert into s2
        int minInsertions = n - len;

        // Total operations needed
        return minDeletions + minInsertions;
    }

    public static void main(String[] args) {
        String s1 = "AGGTAB";
        String s2 = "GXTXAYB";

        int res = minOperations(s1, s2);
        System.out.println(res);
    }
}
Python
# Python program to find the minimum number of insertions
# and deletions using recursion
 
def lcs(s1, s2, m, n):

    # Base case: If either string is empty,
    # the LCS length is 0
    if m == 0 or n == 0:
        return 0

    # If the last characters of both substrings match
    if s1[m - 1] == s2[n - 1]:

        # Include the matching character in LCS and 
        # recurse for remaining substrings
        return 1 + lcs(s1, s2, m - 1, n - 1)
    else:
      
        # If the last characters do not match, 
        # find the maximum LCS length by:
        # 1. Excluding the last character of s1
        # 2. Excluding the last character of s2
        return max(lcs(s1, s2, m, n - 1), lcs(s1, s2, m - 1, n))


def minOperations(s1, s2):

    m = len(s1)
    n = len(s2)

    # the length of LCS for s1[0..m-1] and s2[0..n-1]
    lengthLcs = lcs(s1, s2, m, n)

    # Characters to delete from str1
    minDeletions = m - lengthLcs

    # Characters to insert into str1
    minInsertions = n - lengthLcs

    # Total operations needed
    return minDeletions + minInsertions


if __name__ == "__main__":
    s1 = "AGGTAB"
    s2 = "GXTXAYB"

    result = minOperations(s1, s2)
    print(result)
C#
// C# program to find the minimum number of insertions and
// deletions using recursion.

using System;
class GfG {
    static int lcs(string s1, string s2, int m, int n) {
      
        // Base case: If either string is empty, the LCS
        // length is 0
        if (m == 0 || n == 0)
            return 0;

        // If the last characters of both substrings match
        if (s1[m - 1] == s2[n - 1]) {
          
            // Include the matching character in LCS
            // and recurse for remaining substrings
            return 1 + lcs(s1, s2, m - 1, n - 1);
        }
        else {
          
            // If the last characters do not match,
            // find the maximum LCS length by:
            // 1. Excluding the last character of s1
            // 2. Excluding the last character of s2
            return Math.Max(lcs(s1, s2, m, n - 1),
                            lcs(s1, s2, m - 1, n));
        }
    }

    static int minOperations(string s1, string s2) {
        int m = s1.Length;
        int n = s2.Length;

        // the length of LCS for s1[0..m-1] and
        // s2[0..n-1]
        int lengthLcs = lcs(s1, s2, m, n);

        // Characters to delete from s1
        int minDeletions = m - lengthLcs;

        // Characters to insert into s2
        int minInsertions = n - lengthLcs;

        // Total operations needed
        return minDeletions + minInsertions;
    }

    static void Main(string[] args) {
        string s1 = "AGGTAB";
        string s2 = "GXTXAYB";

        int result = minOperations(s1, s2);
        Console.WriteLine(result);
    }
}
JavaScript
// JavaScript program to find the minimum number of
// insertions and deletions using recursion

function lcs(s1, s2, m, n) {

    // Base case: If either string is empty, the LCS length
    // is 0
    if (m === 0 || n === 0) {
        return 0;
    }

    // If the last characters of both substrings match
    if (s1[m - 1] === s2[n - 1]) {
     
        // Include the matching character in LCS and recurse
        // for remaining substrings
        return 1 + lcs(s1, s2, m - 1, n - 1);
    }
    else {
    
        // If the last characters do not match, find the
        // maximum LCS length by:
        // 1. Excluding the last character of s1
        // 2. Excluding the last character of s2
        return Math.max(lcs(s1, s2, m, n - 1),
                        lcs(s1, s2, m - 1, n));
    }
}

function minOperations(s1, s2) {
    const m = s1.length;
    const n = s2.length;

    // Length of the LCS
    const len = lcs(s1, s2, m, n);

    // Characters to delete from s1
    const minDeletions = m - len;

    // Characters to insert into s1
    const minInsertions = n - len;

    // Total operations needed
    return minDeletions + minInsertions;
}

const s1 = "AGGTAB";
const s2 = "GXTXAYB";

const res = minOperations(s1, s2);
console.log(res);

Output
5

Using Top-Down DP (Memoization) – O(n^2) Time and O(n^2) Space

In this approach, we apply memoization to store the results of overlapping subproblems while finding the Longest Common Subsequence (LCS). A 2D array memo is used to save the LCS lengths for different substrings of the two input strings, ensuring that each subproblem is solved only once.
This method is similar to Longest Common Subsequence (LCS) problem using memoization.

C++
// C++ program to find the minimum of insertion and deletion
// using memoization.

#include <iostream>
#include <vector>
using namespace std;

int lcs(string &s1, string &s2, int m, int n, 
        vector<vector<int>> &memo) {
  
    // Base case: If either string is empty, the LCS length is 0
    if (m == 0 || n == 0)
        return 0;

     // If the value is already computed, return
    // it from the memo array
     if(memo[m][n]!=-1)
        return memo[m][n];
   
    // If the last characters of both substrings match
    if (s1[m - 1] == s2[n - 1])
      
        // Include the matching character in LCS and recurse for
       // remaining substrings
        return memo[m][n] = 1 + lcs(s1, s2, m - 1, n - 1, memo);

    else
      
        // If the last characters do not match, find the maximum LCS length by:
        // 1. Excluding the last character of s1
        // 2. Excluding the last character of s2
        return memo[m][n] = max(lcs(s1, s2, m, n - 1, memo),
                                lcs(s1, s2, m - 1, n, memo));
}

int minOperations(string s1, string s2) {
  
    int m = s1.size();  
    int n = s2.size();  
     
     // Initialize the memoization array with -1.
  vector<vector<int>> memo = vector<vector<int>>
                            (m+1,vector<int>(n+1,-1));
   
    // the length of the LCS for 
      // s1[0..m-1] and s2[0..n-1]
    int len = lcs(s1, s2, m, n, memo);

    // Characters to delete from s1
    int minDeletions = m - len;

    // Characters to insert into s1
    int minInsertions = n - len;

    // Total operations needed
    int total = minDeletions + minInsertions;
    return total;
}

int main() {
  
    string s1 = "AGGTAB";
    string s2 = "GXTXAYB";
    int res = minOperations(s1, s2);
    cout << res;
    return 0;
}
Java
// Java program to find the minimum of insertion and deletion
// using memoization.

class GfG {

    static int lcs(String s1, String s2, int m, int n, int[][] memo) {
      
        // Base case: If either string is empty, 
          // the LCS length is 0
        if (m == 0 || n == 0) {    
            return 0;
        }

        // If the value is already computed, return it
          // from the memo array
        if (memo[m][n] != -1) {
            return memo[m][n];
        }

        // If the last characters of both substrings match
        if (s1.charAt(m - 1) == s2.charAt(n - 1)) {

            // Include the matching character in LCS and recurse for
           // remaining substrings
            memo[m][n] = 1 + lcs(s1, s2, m - 1, n - 1, memo);
        }
        else {
          
            // If the last characters do not match,
            // find the maximum LCS length by:
            // 1. Excluding the last character of s1
            // 2. Excluding the last character of s2
            memo[m][n] = Math.max(lcs(s1, s2, m, n - 1, memo),
                                  lcs(s1, s2, m - 1, n, memo));
        }
        return memo[m][n];
    }

    static int minOperations(String s1, String s2) {
      
        int m = s1.length();   
        int n = s2.length();   

        // Initialize the memoization array with -1 
          // (indicating uncalculated values)
        int[][] memo = new int[m + 1][n + 1];
        for (int i = 0; i <= m; i++) {
            for (int j = 0; j <= n; j++) {
                memo[i][j] = -1;
            }
        }

        // the length of LCS for s1[0..m-1] and s2[0..n-1]
        int len = lcs(s1, s2, m, n, memo);

        // Characters to delete from s1
        int minDeletions = m - len;

        // Characters to insert into s1
        int minInsertions = n - len;

        // Total operations needed
        return minDeletions + minInsertions;
    }

   static void main(String[] args) {
      
        String s1 = "AGGTAB";   
        String s2 = "GXTXAYB";  
        int res = minOperations(s1, s2);  
        System.out.println(res);   
    }
}
Python
# Python program to find the minimum number of insertions and 
# deletions using memoization

def lcs(s1, s2, m, n, memo):
  
    # Base case: If either string is empty, the LCS length is 0
    if m == 0 or n == 0:
        return 0

    # If the value is already computed, 
    # return it from the memo array
    if memo[m][n] != -1:
        return memo[m][n]

    # If the last characters of both substrings match
    if s1[m - 1] == s2[n - 1]:
      
        # Include the matching character in LCS and 
        # recurse for remaining substrings
        memo[m][n] = 1 + lcs(s1, s2, m - 1, n - 1, memo)
    else:
      
        # If the last characters do not match, 
        # find the maximum LCS length by:
        # 1. Excluding the last character of s1
        # 2. Excluding the last character of s2
        memo[m][n] = max(lcs(s1, s2, m, n - 1, memo),
                         lcs(s1, s2, m - 1, n, memo))
    
    # Return the computed value
    return memo[m][n]


def minOperations(s1, s2):
    m = len(s1)   
    n = len(s2)   

    # Initialize the memoization array with -1
    # (indicating uncalculated values)
    memo = [[-1 for _ in range(n + 1)] for _ in range(m + 1)]

    # Calculate the length of LCS for s1[0..m-1] and s2[0..n-1]
    lengthLcs = lcs(s1, s2, m, n, memo)

    # Characters to delete from s1
    minDeletions = m - lengthLcs

    # Characters to insert into s1
    minInsertions = n - lengthLcs

    # Total operations needed
    return minDeletions + minInsertions


if __name__ == "__main__":
    s1 = "AGGTAB"
    s2 = "GXTXAYB"

    res = minOperations(s1, s2)
    print(res)  
C#
// C# program to find the minimum of insertion and deletion
// using memoization.

using System;

class GfG {
    
    static int lcs(string s1, string s2, int m, int n,
                       int[, ] memo) {
      
        // Base case: If either string is empty, the LCS
        // length is 0
        if (m == 0 || n == 0) {
            return 0;
        }

        // If the value is already computed, return it from
        // the memo array
        if (memo[m, n] != -1) {
            return memo[m, n];
        }

        // If the last characters of both substrings match
        if (s1[m - 1] == s2[n - 1]) {
          
            // Include the matching character in LCS and
            // recurse for remaining substrings
            memo[m, n]
                = 1 + lcs(s1, s2, m - 1, n - 1, memo);
        }
        else {
          
            // If the last characters do not match, find the
            // maximum LCS length by:
            // 1. Excluding the last character of s1
            // 2. Excluding the last character of s2
            memo[m, n]
                = Math.Max(lcs(s1, s2, m, n - 1, memo),
                           lcs(s1, s2, m - 1, n, memo));
        }

        // Return the computed value
        return memo[m, n];
    }
 
    static int minOperations(string s1, string s2) {
      
        int m = s1.Length;  
        int n = s2.Length;  

        // Initialize the memoization array with -1
        // (indicating uncalculated values)
        int[, ] memo = new int[m + 1, n + 1];
        for (int i = 0; i <= m; i++) {
            for (int j = 0; j <= n; j++) {
                memo[i, j] = -1;
            }
        }

        // Calculate the length of LCS for s1[0..m-1] and
        // s2[0..n-1]
        int lengthLcs = lcs(s1, s2, m, n, memo);

        // Characters to delete from s1
        int minDeletions = m - lengthLcs;

        // Characters to insert into s1
        int minInsertions = n - lengthLcs;

        // Total operations needed
        return minDeletions + minInsertions;
    }

   
    static void Main(string[] args) {
      
        string s1 = "AGGTAB";
        string s2 = "GXTXAYB";
        int res = minOperations(s1, s2);
        Console.WriteLine(res);  
    }
}
JavaScript
// JavaScript program to find the minimum number of
// insertions and deletions using memoization

function lcs(s1, s2, m, n, memo) {

    // Base case: If either string is empty, the LCS length
    // is 0
    if (m === 0 || n === 0) {
        return 0;
    }

    // If the value is already computed, return it from the
    // memo array
    if (memo[m][n] !== -1) {
        return memo[m][n];
    }

    // If the last characters of both substrings match
    if (s1[m - 1] === s2[n - 1]) {
    
        // Include the matching character in LCS and recurse
        // for remaining substrings
        memo[m][n] = 1 + lcs(s1, s2, m - 1, n - 1, memo);
    }
    else {
    
        // If the last characters do not match, find the
        // maximum LCS length by:
        // 1. Excluding the last character of s1
        // 2. Excluding the last character of s2
        memo[m][n] = Math.max(lcs(s1, s2, m, n - 1, memo),
                              lcs(s1, s2, m - 1, n, memo));
    }
  
    return memo[m][n];
}

function minOperations(s1, s2){

    const m = s1.length;
    const n = s2.length;

    // Initialize the memoization array with -1 (indicating
    // uncalculated values)
    const memo = Array.from({length : m + 1},
                            () => Array(n + 1).fill(-1));

    // Calculate the length of LCS for s1[0..m-1] and
    // s2[0..n-1]
    const len = lcs(s1, s2, m, n, memo);

    // Characters to delete from s1
    const minDeletions = m - len;

    // Characters to insert into s1
    const minInsertions = n - len;

    // Total operations needed
    return minDeletions + minInsertions;
}

const s1 = "AGGTAB";
const s2 = "GXTXAYB";

const res = minOperations(s1, s2);
console.log(res);

Output
5

Using Bottom-Up DP (Tabulation) – O(n^2) Time and O(n^2) Space

The approach is similar to the previous one, just instead of breaking down the problem recursively, we iteratively build up the solution by calculating in bottom-up manner. We maintain a 2D dp[][] table, such that dp[i][j], stores the Longest Common Subsequence (LCS) for the subproblem(i, j).
This approach is similar to finding LCS in bottom-up manner.

C++
// C++ program to find the minimum of insertion and deletion
// using tabulation.

#include <iostream>
#include <vector>
using namespace std;
 
int lcs(string &s1, string &s2) {
  
    int m = s1.size();
    int n = s2.size();

    // Initializing a matrix of size (m+1)*(n+1)
    vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));

    // Building dp[m+1][n+1] in bottom-up fashion
    for (int i = 1; i <= m; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (s1[i - 1] == s2[j - 1])
                dp[i][j] = dp[i - 1][j - 1] + 1;
            else
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
        }
    }

    // dp[m][n] contains length of LCS for s1[0..m-1]
    // and s2[0..n-1]
    return dp[m][n];
}

int minOperations(string s1, string s2) {
  
    int m = s1.size();
    int n = s2.size();

    // the length of the LCS for
      // s1[0..m-1] and s2[0..n-1]
    int len = lcs(s1, s2);

    // Characters to delete from s1
    int minDeletions = m - len;

    // Characters to insert into s1
    int minInsertions = n - len;

    // Total operations needed
    int total = minDeletions + minInsertions;
    return total;
}
int main() {
  
    string s1 = "AGGTAB";
    string s2 = "GXTXAYB";
    int res = minOperations(s1, s2);
    cout << res;

    return 0;
}
Java
// Java program to find the minimum of insertion and
// deletion using tabulation.

class GfG {
 
    static int lcs(String s1, String s2) {
      
        int m = s1.length();
        int n = s2.length();

        // Initializing a matrix of size (m+1)*(n+1)
        int[][] dp = new int[m + 1][n + 1];

        // Building dp[m+1][n+1] in bottom-up fashion
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (s1.charAt(i - 1) == s2.charAt(j - 1))
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                else
                    dp[i][j] = Math.max(dp[i - 1][j],
                                        dp[i][j - 1]);
            }
        }

        // dp[m][n] contains length of LCS for s1[0..m-1]
        // and s2[0..n-1]
        return dp[m][n];
    }

    static int minOperations(String s1, String s2) {
      
        int m = s1.length();
        int n = s2.length();

        // the length of the LCS for s1[0..m-1] and
        // str2[0..n-1]
        int len = lcs(s1, s2);

        // Characters to delete from s1
        int minDeletions = m - len;

        // Characters to insert into s1
        int minInsertions = n - len;

        // Total operations needed
        return minDeletions + minInsertions;
    }

    public static void main(String[] args) {
      
        String s1 = "AGGTAB";
        String s2 = "GXTXAYB";
        int res = minOperations(s1, s2);
        System.out.println(res);
    }
}
Python
# Python program to find the minimum of insertion and deletion
# using tabulation.
  
def lcs(s1, s2):
    m = len(s1)
    n = len(s2)

    # Initializing a matrix of size (m+1)*(n+1)
    dp = [[0] * (n + 1) for _ in range(m + 1)]

    # Building dp[m+1][n+1] in bottom-up fashion
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if s1[i - 1] == s2[j - 1]:
                dp[i][j] = dp[i - 1][j - 1] + 1
            else:
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])

    # dp[m][n] contains length of LCS for
    # s1[0..m-1] and s2[0..n-1]
    return dp[m][n]


def minOperations(s1, s2):
    m = len(s1)
    n = len(s2)

    # the length of the LCS for 
    # s1[0..m-1] and s2[0..n-1]
    lengthLcs = lcs(s1, s2)

    # Characters to delete from s1
    minDeletions = m - lengthLcs

    # Characters to insert into s1
    minInsertions = n - lengthLcs

    # Total operations needed
    return minDeletions + minInsertions


s1 = "AGGTAB"
s2 = "GXTXAYB"
res = minOperations(s1, s2)
print(res)
C#
// C# program to find the minimum of insertion and deletion
// using tabulation.

using System;

class GfG {
    
    static int Lcs(string s1, string s2) {
      
        int m = s1.Length;
        int n = s2.Length;

        // Initializing a matrix of size (m+1)*(n+1)
        int[, ] dp = new int[m + 1, n + 1];

        // Building dp[m+1][n+1] in bottom-up fashion
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (s1[i - 1] == s2[j - 1])
                    dp[i, j] = dp[i - 1, j - 1] + 1;
                else
                    dp[i, j] = Math.Max(dp[i - 1, j],
                                        dp[i, j - 1]);
            }
        }

        // dp[m, n] contains length of LCS for s1[0..m-1]
        // and s2[0..n-1]
        return dp[m, n];
    }

    static int minOperations(string s1, string s2) {
      
        int m = s1.Length;
        int n = s2.Length;

        // the length of the LCS for s1[0..m-1] and
        // s2[0..n-1]
        int len = Lcs(s1, s2);

        // Characters to delete from str1
        int minDeletions = m - len;

        // Characters to insert into str1
        int minInsertions = n - len;

        // Total operations needed
        return minDeletions + minInsertions;
    }

    static void Main() {
      
        string s1 = "AGGTAB";
        string s2 = "GXTXAYB";
        int res = minOperations(s1, s2);
        Console.WriteLine(res);
    }
}
JavaScript
// JavaScript program to find the minimum of insertion and
// deletion using tabulation.

function lcs(s1, s2) {

    let m = s1.length;
    let n = s2.length;

    // Initializing a matrix of size (m+1)*(n+1)
    let dp = Array(m + 1).fill().map(
        () => Array(n + 1).fill(0));

    // Building dp[m+1][n+1] in bottom-up fashion
    for (let i = 1; i <= m; ++i) {
        for (let j = 1; j <= n; ++j) {
            if (s1[i - 1] === s2[j - 1])
                dp[i][j] = dp[i - 1][j - 1] + 1;
            else
                dp[i][j]
                    = Math.max(dp[i - 1][j], dp[i][j - 1]);
        }
    }

    // dp[m][n] contains length of LCS for s1[0..m-1] and
    // s2[0..n-1]
    return dp[m][n];
}

function minOperations(s1, s2) {

    let m = s1.length;
    let n = s2.length;

    // the length of the LCS for s1[0..m-1] and s2[0..n-1]
    let len = lcs(s1, s2);

    // Characters to delete from s1
    let minDeletions = m - len;

    // Characters to insert into s1
    let minInsertions = n - len;

    // Total operations needed
    return minDeletions + minInsertions;
}

let s1 = "AGGTAB";
let s2 = "GXTXAYB";
let res = minOperations(s1, s2);
console.log(res);

Output
5

Using Bottom-Up DP (Space-Optimization)– O(n^2) Time and O(n) Space

In the previous approach, the longest common subsequence (LCS) algorithm uses O(n * n) space to store the entire dp table. However, since each value in dp[i][j] only depends on the current row and the previous row, we don’t need to store the entire table. This can be optimized by storing only the current and previous rows. For more details, refer to A Space Optimized Solution of LCS.

C++
// C++ program to find the minimum of insertion and deletion
// using space optimized.

#include <bits/stdc++.h>
using namespace std;

int lcs(string &s1, string &s2) {
  
    int m = s1.length(), n = s2.length();

    vector<vector<int>> dp(2, vector<int>(n + 1));

    for (int i = 0; i <= m; i++) {

        // Compute current binary index. If i is even
        // then curr = 0, else 1
        bool curr = i & 1;

        for (int j = 0; j <= n; j++) {
          
            // Initialize first row and first column with 0
            if (i == 0 || j == 0)
                dp[curr][j] = 0;

            else if (s1[i - 1] == s2[j - 1])
                dp[curr][j] = dp[1 - curr][j - 1] + 1;

            else
                dp[curr][j] = max(dp[1 - curr][j], dp[curr][j - 1]);
        }
    }

    return dp[m & 1][n];
}

int minOperations(string s1, string s2) {
    int m = s1.size();
    int n = s2.size();

    // the length of the LCS for s1[0..m-1] and s2[0..n-1]
    int len = lcs(s1, s2);

    // Characters to delete from s1
    int minDeletions = m - len;

    // Characters to insert into s1
    int minInsertions = n - len;

    // Total operations needed
    int total = minDeletions + minInsertions;
    return total;
}

int main() {
    string s1 = "AGGTAB";
    string s2 = "GXTXAYB";
    int res = minOperations(s1, s2);
    cout << res;
    return 0;
}
Java
// Java program to find the minimum of insertion and
// deletion using space optimized.

class GfG {
 
    static int lcs(String s1, String s2) {
      
        int m = s1.length();
        int n = s2.length();

        // Initializing a 2D array with size (2) x (n + 1)
        int[][] dp = new int[2][n + 1];

        for (int i = 0; i <= m; i++) {

            // Compute current binary index. If i is even,
            // then curr = 0, else 1
            int curr = i % 2;

            for (int j = 0; j <= n; j++) {
              
                // Initialize first row and first column
                // with 0
                if (i == 0 || j == 0)
                    dp[curr][j] = 0;
                else if (s1.charAt(i - 1)
                         == s2.charAt(j - 1))
                    dp[curr][j] = dp[1 - curr][j - 1] + 1;
                else
                    dp[curr][j] = Math.max(dp[1 - curr][j],
                                           dp[curr][j - 1]);
            }
        }

        return dp[m % 2][n];
    }

    static int minOperations(String s1, String s2) {
      
        int m = s1.length();
        int n = s2.length();

        // the length of the LCS for s1[0..m-1] and
        // s2[0..n-1]
        int len = lcs(s1, s2);

        // Characters to delete from s1
        int minDeletions = m - len;

        // Characters to insert into s1
        int minInsertions = n - len;

        // Total operations needed
        return minDeletions + minInsertions;
    }

    public static void main(String[] args) {
      
        String s1 = "AGGTAB";
        String s2 = "GXTXAYB";
        int res = minOperations(s1, s2);
        System.out.println(res);
    }
}
Python
# Python program to find the minimum of insertion and deletion
# using space optimized.
 
def lcs(s1, s2):
    m = len(s1)
    n = len(s2)

    # Initializing a matrix of size (2)*(n+1)
    dp = [[0] * (n + 1) for _ in range(2)]

    for i in range(m + 1):

        # Compute current binary index. If i is even
        # then curr = 0, else 1
        curr = i % 2

        for j in range(n + 1):

            # Initialize first row and first column with 0
            if i == 0 or j == 0:
                dp[curr][j] = 0

            # If the last characters of both substrings match
            elif s1[i - 1] == s2[j - 1]:
                dp[curr][j] = dp[1 - curr][j - 1] + 1

            # If the last characters do not match,
            # find the maximum LCS length by:
            # 1. Excluding the last character of s1
            # 2. Excluding the last character of s2
            else:
                dp[curr][j] = max(dp[1 - curr][j], dp[curr][j - 1])

    # dp[m & 1][n] contains length of LCS for s1[0..m-1] and s2[0..n-1]
    return dp[m % 2][n]


def minOperations(s1, s2):
    m = len(s1)
    n = len(s2)

    # the length of the LCS for s1[0..m-1] and s2[0..n-1]
    length = lcs(s1, s2)

    # Characters to delete from s1
    minDeletions = m - length

    # Characters to insert into s1
    minInsertions = n - length

    # Total operations needed
    return minDeletions + minInsertions


s1 = "AGGTAB"
s2 = "GXTXAYB"
res = minOperations(s1, s2)
print(res)
C#
// C# program to find the minimum of insertion and deletion
// using space optimized.

using System;

class GfG {
    static int lcs(string s1, string s2) {
      
        int m = s1.Length;
        int n = s2.Length;

        // Initializing a matrix of size (2)*(n+1)
        int[][] dp = new int[2][];
        dp[0] = new int[n + 1];
        dp[1] = new int[n + 1];

        for (int i = 0; i <= m; i++) {
          
            // Compute current binary index. If i is even
            // then curr = 0, else 1
            int curr = i % 2;

            for (int j = 0; j <= n; j++) {
              
                // Initialize first row and first column
                // with 0
                if (i == 0 || j == 0)
                    dp[curr][j] = 0;

                // If the last characters of both substrings
                // match
                else if (s1[i - 1] == s2[j - 1])
                    dp[curr][j] = dp[1 - curr][j - 1] + 1;

                // If the last characters do not match,
                // find the maximum LCS length by:
                // 1. Excluding the last character of s1
                // 2. Excluding the last character of s2
                else
                    dp[curr][j] = Math.Max(dp[1 - curr][j],
                                           dp[curr][j - 1]);
            }
        }

        // dp[m & 1][n] contains length of LCS for
        // s1[0..m-1] and s2[0..n-1]
        return dp[m % 2][n];
    }

    static int minOperations(string s1, string s2) {
      
        int m = s1.Length;
        int n = s2.Length;

        // the length of the LCS for s1[0..m-1] and
        // s2[0..n-1]
        int length = lcs(s1, s2);

        // Characters to delete from s1
        int minDeletions = m - length;

        // Characters to insert into s1
        int minInsertions = n - length;

        // Total operations needed
        return minDeletions + minInsertions;
    }

    static void Main(string[] args) {
      
        string s1 = "AGGTAB";
        string s2 = "GXTXAYB";
        int res = minOperations(s1, s2);
        Console.WriteLine(res);
    }
}
JavaScript
// JavaScript program to find the minimum of insertion and
// deletion using space optimized.

function lcs(s1, s2) {

    const m = s1.length;
    const n = s2.length;

    // Initializing a matrix of size (2)*(n+1)
    const dp
        = Array(2).fill().map(() => Array(n + 1).fill(0));

    for (let i = 0; i <= m; i++) {
    
        // Compute current binary index. If i is even
        // then curr = 0, else 1
        const curr = i % 2;

        for (let j = 0; j <= n; j++) {
        
            // Initialize first row and first column with 0
            if (i === 0 || j === 0)
                dp[curr][j] = 0;

            // If the last characters of both substrings
            // match
            else if (s1[i - 1] === s2[j - 1])
                dp[curr][j] = dp[1 - curr][j - 1] + 1;

            // If the last characters do not match,
            // find the maximum LCS length by:
            // 1. Excluding the last character of s1
            // 2. Excluding the last character of s2
            else
                dp[curr][j] = Math.max(dp[1 - curr][j],
                                       dp[curr][j - 1]);
        }
    }

    // dp[m & 1][n] contains length of LCS for s1[0..m-1]
    // and s2[0..n-1]
    return dp[m % 2][n];
}

function minOperations(s1, s2) {

    const m = s1.length;
    const n = s2.length;

    // the length of the LCS for s1[0..m-1] and s2[0..n-1]
    const length = lcs(s1, s2);

    // Characters to delete from s1
    const minDeletions = m - length;

    // Characters to insert into s1
    const minInsertions = n - length;

    // Total operations needed
    return minDeletions + minInsertions;
}

const s1 = "AGGTAB";
const s2 = "GXTXAYB";
const res = minOperations(s1, s2);
console.log(res);

Output
5


Next Article
Article Tags :
Practice Tags :

Similar Reads

three90RightbarBannerImg
  翻译: