Minimum number of deletions and insertions to transform one string into another
Last Updated : 16 Nov, 2024
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);
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);
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);
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);