Minimum number of deletions and insertions to transform one string into another
Last Updated :
11 Nov, 2023
Given two strings ‘str1’ and ‘str2’ of size m and n respectively. The task is to remove/delete and insert the minimum number of characters from/in str1 to transform it into str2. It could be possible that the same character needs to be removed/deleted from one point of str1 and inserted at some another point.
Example 1:
Input :
str1 = "heap", str2 = "pea"
Output :
Minimum Deletion = 2 and
Minimum Insertion = 1
Explanation:
p and h deleted from heap
Then, p is inserted at the beginning
One thing to note, though p was required yet
it was removed/deleted first from its position and
then it is inserted to some other position.
Thus, p contributes one to the deletion_count
and one to the insertion_count.
Example 2:
Input :
str1 = "geeksforgeeks", str2 = "geeks"
Output :
Minimum Deletion = 8
Minimum Insertion = 0
Simple Approach:
A simple approach is to consider all subsequences of str1 and for each subsequence calculate minimum deletions and insertions so as to transform it into str2. A very complex method and the time complexity of this solution is exponential.
Efficient Approach:
An efficient approach uses the concept of finding the length of the longest common subsequence of the given two sequences.
Algorithm:
- str1 and str2 be the given strings.
- m and n be their lengths respectively.
- len be the length of the longest common subsequence of str1 and str2
- minimum number of deletions minDel = m – len (as we only need to delete from str1 because we are reducing it to str2)
- minimum number of Insertions minInsert = n – len (as we are inserting x in str1 , x is a number of characters in str2 which are not taking part in the string which is longest common subsequence )
Below is the implementation of the above code:
C++
#include <bits/stdc++.h>
using namespace std;
int lcs(string str1, string str2, int m, int n)
{
int L[m + 1][n + 1];
int i, j;
for (i = 0; i <= m; i++) {
for (j = 0; j <= n; j++) {
if (i == 0 || j == 0)
L[i][j] = 0;
else if (str1.at(i - 1) == str2.at(j - 1))
L[i][j] = L[i - 1][j - 1] + 1;
else
L[i][j] = max(L[i - 1][j], L[i][j - 1]);
}
}
return L[m][n];
}
void printMinDelAndInsert(string str1, string str2)
{
int m = str1.size();
int n = str2.size();
int len = lcs(str1, str2, m, n);
cout << "Minimum number of deletions = " << (m - len)
<< endl;
cout << "Minimum number of insertions = " << (n - len)
<< endl;
}
int main()
{
string str1 = "heap" ;
string str2 = "pea" ;
printMinDelAndInsert(str1, str2);
return 0;
}
|
Java
import java.io.*;
class GFG {
static int lcs(String str1, String str2, int m, int n)
{
int L[][] = new int [m + 1 ][n + 1 ];
int i, j;
for (i = 0 ; i <= m; i++) {
for (j = 0 ; j <= n; j++) {
if (i == 0 || j == 0 )
L[i][j] = 0 ;
else if (str1.charAt(i - 1 )
== str2.charAt(j - 1 ))
L[i][j] = L[i - 1 ][j - 1 ] + 1 ;
else
L[i][j] = Math.max(L[i - 1 ][j],
L[i][j - 1 ]);
}
}
return L[m][n];
}
static void printMinDelAndInsert(String str1,
String str2)
{
int m = str1.length();
int n = str2.length();
int len = lcs(str1, str2, m, n);
System.out.println( "Minimum number of "
+ "deletions = " );
System.out.println(m - len);
System.out.println( "Minimum number of "
+ "insertions = " );
System.out.println(n - len);
}
public static void main(String[] args)
{
String str1 = new String( "heap" );
String str2 = new String( "pea" );
printMinDelAndInsert(str1, str2);
}
}
|
Python3
def lcs(str1, str2, m, n):
L = [[ 0 for i in range (n + 1 )]
for i in range (m + 1 )]
for i in range (m + 1 ):
for j in range (n + 1 ):
if (i = = 0 or j = = 0 ):
L[i][j] = 0
elif (str1[i - 1 ] = = str2[j - 1 ]):
L[i][j] = L[i - 1 ][j - 1 ] + 1
else :
L[i][j] = max (L[i - 1 ][j],
L[i][j - 1 ])
return L[m][n]
def printMinDelAndInsert(str1, str2):
m = len (str1)
n = len (str2)
leng = lcs(str1, str2, m, n)
print ( "Minimum number of deletions = " ,
m - leng, sep = ' ' )
print ( "Minimum number of insertions = " ,
n - leng, sep = ' ' )
str1 = "heap"
str2 = "pea"
printMinDelAndInsert(str1, str2)
|
C#
using System;
class GFG {
static int lcs( string str1, string str2, int m, int n)
{
int [, ] L = new int [m + 1, n + 1];
int i, j;
for (i = 0; i <= m; i++) {
for (j = 0; j <= n; j++) {
if (i == 0 || j == 0)
L[i, j] = 0;
else if (str1[i - 1] == str2[j - 1])
L[i, j] = L[i - 1, j - 1] + 1;
else
L[i, j] = Math.Max(L[i - 1, j],
L[i, j - 1]);
}
}
return L[m, n];
}
static void printMinDelAndInsert( string str1,
string str2)
{
int m = str1.Length;
int n = str2.Length;
int len = lcs(str1, str2, m, n);
Console.Write( "Minimum number of "
+ "deletions = " );
Console.WriteLine(m - len);
Console.Write( "Minimum number of "
+ "insertions = " );
Console.Write(n - len);
}
public static void Main()
{
string str1 = new string ( "heap" );
string str2 = new string ( "pea" );
printMinDelAndInsert(str1, str2);
}
}
|
Javascript
<script>
function lcs(str1, str2, m, n)
{
let L = new Array(m + 1);
let i, j;
for (i = 0; i <= m; i++)
{
L[i] = new Array(n + 1);
for (j = 0; j <= n; j++)
{
L[i][j] = 0;
}
}
for (i = 0; i <= m; i++) {
for (j = 0; j <= n; j++) {
if (i == 0 || j == 0)
L[i][j] = 0;
else if (str1[i - 1]
== str2[j - 1])
L[i][j] = L[i - 1][j - 1] + 1;
else
L[i][j] = Math.max(L[i - 1][j],
L[i][j - 1]);
}
}
return L[m][n];
}
function printMinDelAndInsert(str1, str2)
{
let m = str1.length;
let n = str2.length;
let len = lcs(str1, str2, m, n);
document.write( "Minimum number of "
+ "deletions = " );
document.write((m - len) + "</br>" );
document.write( "Minimum number of "
+ "insertions = " );
document.write((n - len) + "</br>" );
}
let str1 = "heap" ;
let str2 = "pea" ;
printMinDelAndInsert(str1, str2);
</script>
|
Output
Minimum number of deletions = 2
Minimum number of insertions = 1
Time Complexity: O(m * n)
Auxiliary Space: O(m * n)
Method 2: Top-down approach using memoization
This method also uses the idea of finding the length of the longest common subsequence of the given two sequences. But this approach is using a top-down approach using memoization.
C++
#include <bits/stdc++.h>
using namespace std;
int dp[1001][1001];
int lcs(string& s1, string& s2, int i, int j)
{
if (i == 0 || j == 0) {
return 0;
}
if (dp[i][j] != -1) {
return dp[i][j];
}
if (s1[i - 1] == s2[j - 1]) {
return dp[i][j] = 1 + lcs(s1, s2, i - 1, j - 1);
}
else {
return dp[i][j] = max(lcs(s1, s2, i, j - 1),
lcs(s1, s2, i - 1, j));
}
}
void printMinDelAndInsert(string str1, string str2)
{
int m = str1.size();
int n = str2.size();
dp[m][n];
memset (dp, -1, sizeof (dp));
int len = lcs(str1, str2, m, n);
cout << "Minimum number of deletions = " << (m - len)
<< endl;
cout << "Minimum number of insertions = " << (n - len)
<< endl;
}
int main()
{
string str1 = "heap" ;
string str2 = "pea" ;
printMinDelAndInsert(str1, str2);
return 0;
}
|
Java
import java.io.*;
import java.util.Arrays;
class GFG {
public static int dp[][]= new int [ 1001 ][ 1001 ];
static int lcs(String str1, String str2, int i, int j)
{
if (i == 0 || j == 0 ) {
return 0 ;
}
if (dp[i][j] != - 1 ) {
return dp[i][j];
}
if (str1.charAt(i - 1 ) == str2.charAt(j - 1 )) {
return dp[i][j] = 1 + lcs(str1, str2, i - 1 , j - 1 );
}
else {
return dp[i][j] = Math.max(lcs(str1, str2, i, j - 1 ),
lcs(str1, str2, i - 1 , j));
}
}
static void printMinDelAndInsert(String str1,
String str2)
{
int m = str1.length();
int n = str2.length();
int len = lcs(str1, str2, m, n);
System.out.println( "Minimum number of "
+ "deletions = " +(m - len));
System.out.println( "Minimum number of "
+ "insertions = " +(n - len));
}
public static void main(String[] args)
{
String str1 = new String( "heap" );
String str2 = new String( "pea" );
for ( int i= 0 ;i< 1001 ;i++){
Arrays.fill(dp[i],- 1 );
}
printMinDelAndInsert(str1, str2);
}
}
|
Python3
dp = [[ - 1 for i in range ( 1001 )] for j in range ( 1001 )]
def lcs(s1, s2, i, j):
if i = = 0 or j = = 0 :
return 0
if dp[i][j] ! = - 1 :
return dp[i][j]
if s1[i - 1 ] = = s2[j - 1 ]:
dp[i][j] = 1 + lcs(s1, s2, i - 1 , j - 1 )
return dp[i][j]
else :
dp[i][j] = max (lcs(s1, s2, i, j - 1 ), lcs(s1, s2, i - 1 , j))
return dp[i][j]
def printMinDelAndInsert(str1, str2):
m = len (str1)
n = len (str2)
dp = [[ - 1 for i in range (n)] for j in range (m)]
length = lcs(str1, str2, m, n)
print ( "Minimum number of deletions = " , (m - length))
print ( "Minimum number of insertions = " , (n - length))
if __name__ = = "__main__" :
str1 = "heap"
str2 = "pea"
printMinDelAndInsert(str1, str2)
|
C#
using System;
namespace MinDelAndInsert {
class Program {
static int [, ] dp = new int [1001, 1001];
static int lcs( string s1, string s2, int i, int j)
{
if (i == 0 || j == 0) {
return 0;
}
if (dp[i, j] != -1) {
return dp[i, j];
}
if (s1[i - 1] == s2[j - 1]) {
return dp[i, j] = 1 + lcs(s1, s2, i - 1, j - 1);
}
else {
return dp[i, j]
= Math.Max(lcs(s1, s2, i, j - 1),
lcs(s1, s2, i - 1, j));
}
}
static void PrintMinDelAndInsert( string str1,
string str2)
{
int m = str1.Length;
int n = str2.Length;
for ( int i = 0; i <= m; i++) {
for ( int j = 0; j <= n; j++) {
dp[i, j] = -1;
}
}
int len = lcs(str1, str2, m, n);
Console.WriteLine( "Minimum number of deletions = "
+ (m - len));
Console.WriteLine( "Minimum number of insertions = "
+ (n - len));
}
static void Main( string [] args)
{
string str1 = "heap" ;
string str2 = "pea" ;
PrintMinDelAndInsert(str1, str2);
}
}
}
|
Javascript
const dp = new Array(1001).fill(-1).map(() => new Array(1001).fill(-1));
const lcs = (s1, s2, i, j) => {
if (i === 0 || j === 0) {
return 0;
}
if (dp[i][j] !== -1) {
return dp[i][j];
}
if (s1[i - 1] === s2[j - 1]) {
dp[i][j] = 1 + lcs(s1, s2, i - 1, j - 1);
return dp[i][j];
}
else {
dp[i][j] = Math.max(lcs(s1, s2, i, j - 1), lcs(s1, s2, i - 1, j));
return dp[i][j];
}
};
const printMinDelAndInsert = (str1, str2) => {
let m = str1.length;
let n = str2.length;
let len = lcs(str1, str2, m, n);
console.log(`Minimum number of deletions = ${m - len}`);
console.log(`Minimum number of insertions = ${n - len}`);
}
let str1 = "heap" ;
let str2 = "pea" ;
printMinDelAndInsert(str1, str2);
|
Output
Minimum number of deletions = 2
Minimum number of insertions = 1
Time Complexity: O(m * n)
Auxiliary Space: O(m * n)
Efficient approach: Space optimization
In previous approach the current value dp[i][j] is only depend upon the current and previous row values of DP. So to optimize the space complexity we use a single 1D array to store the computations.
Implementation steps:
- Create a 1D vector dp of size n+1.
- Set a base case by initializing the values of DP .
- Now iterate over subproblems by the help of nested loop and get the current value from previous computations.
- Now initialize a variable prev used to store the previous computations and a variable temp to store the current computation.
- After every iteration assign the value of prev to temp for further iteration.
- At last return and print the final answer stored in dp[0].
Implementation:
C++
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int lcs(string str1, string str2)
{
int m = str1.size();
int n = str2.size();
vector< int > dp(n + 1, 0);
for ( int i = 1; i <= m; i++) {
int prev = 0;
for ( int j = 1; j <= n; j++) {
int temp = dp[j];
if (str1[i - 1] == str2[j - 1])
dp[j] = prev + 1;
else
dp[j] = max(dp[j], dp[j - 1]);
prev = temp;
}
}
return dp[n];
}
void printMinDelAndInsert(string str1, string str2)
{
int len = lcs(str1, str2);
int m = str1.size();
int n = str2.size();
cout << "Minimum number of deletions = " << (m - len)
<< endl;
cout << "Minimum number of insertions = " << (n - len)
<< endl;
}
int main()
{
string str1 = "heap" ;
string str2 = "pea" ;
printMinDelAndInsert(str1, str2);
return 0;
}
|
Java
import java.util.*;
import java.io.*;
public class GFG {
public static int lcs(String str1, String str2) {
int m = str1.length();
int n = str2.length();
int [] dp = new int [n + 1 ];
for ( int i = 1 ; i <= m; i++) {
int prev = 0 ;
for ( int j = 1 ; j <= n; j++) {
int temp = dp[j];
if (str1.charAt(i - 1 ) == str2.charAt(j - 1 ))
dp[j] = prev + 1 ;
else
dp[j] = Math.max(dp[j], dp[j - 1 ]);
prev = temp;
}
}
return dp[n];
}
public static void printMinDelAndInsert(String str1, String str2) {
int len = lcs(str1, str2);
int m = str1.length();
int n = str2.length();
System.out.println( "Minimum number of deletions = " + (m - len));
System.out.println( "Minimum number of insertions = " + (n - len));
}
public static void main(String[] args) {
String str1 = "heap" ;
String str2 = "pea" ;
printMinDelAndInsert(str1, str2);
}
}
|
Python3
def lcs(str1, str2):
m = len (str1)
n = len (str2)
dp = [[ 0 ] * (n + 1 ) for _ in range (m + 1 )]
for i in range ( 1 , m + 1 ):
for j in range ( 1 , n + 1 ):
if str1[i - 1 ] = = str2[j - 1 ]:
dp[i][j] = dp[i - 1 ][j - 1 ] + 1
else :
dp[i][j] = max (dp[i - 1 ][j], dp[i][j - 1 ])
return dp[m][n]
def print_min_del_and_insert(str1, str2):
len_lcs = lcs(str1, str2)
m = len (str1)
n = len (str2)
min_deletions = m - len_lcs
min_insertions = n - len_lcs
print ( "Minimum number of deletions =" , min_deletions)
print ( "Minimum number of insertions =" , min_insertions)
if __name__ = = "__main__" :
str1 = "heap"
str2 = "pea"
print_min_del_and_insert(str1, str2)
|
C#
using System;
class Program
{
static int LCS( string str1, string str2)
{
int m = str1.Length;
int n = str2.Length;
int [] dp = new int [n + 1];
for ( int i = 1; i <= m; i++)
{
int prev = 0;
for ( int j = 1; j <= n; j++)
{
int temp = dp[j];
if (str1[i - 1] == str2[j - 1])
{
dp[j] = prev + 1;
}
else
{
dp[j] = Math.Max(dp[j], dp[j - 1]);
}
prev = temp;
}
}
return dp[n];
}
static void PrintMinDelAndInsert( string str1, string str2)
{
int len = LCS(str1, str2);
int m = str1.Length;
int n = str2.Length;
Console.WriteLine( "Minimum number of deletions = " + (m - len));
Console.WriteLine( "Minimum number of insertions = " + (n - len));
}
static void Main()
{
string str1 = "heap" ;
string str2 = "pea" ;
PrintMinDelAndInsert(str1, str2);
}
}
|
Javascript
function lcs(str1, str2) {
const m = str1.length;
const n = str2.length;
const dp = new Array(n + 1).fill(0);
for (let i = 1; i <= m; i++) {
let prev = 0;
for (let j = 1; j <= n; j++) {
let temp = dp[j];
if (str1[i - 1] === str2[j - 1]) {
dp[j] = prev + 1;
} else {
dp[j] = Math.max(dp[j], dp[j - 1]);
}
prev = temp;
}
}
return dp[n];
}
function printMinDelAndInsert(str1, str2) {
const len = lcs(str1, str2);
const m = str1.length;
const n = str2.length;
console.log( "Minimum number of deletions = " + (m - len));
console.log( "Minimum number of insertions = " + (n - len));
}
const str1 = "heap" ;
const str2 = "pea" ;
printMinDelAndInsert(str1, str2);
|
Output
Minimum number of deletions = 2
Minimum number of insertions = 1
Time Complexity: O(m * n)
Auxiliary Space: O(n)
This article is contributed by Ayush Jauhari.
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...