Edit Distance Using Dynamic Programming (Further Optimization in Space Complexity)

As discussed the above approach uses two 1-D arrays, now the question is can we achieve our task by using only a single 1-D array?

The answer is Yes and it requires a simple observation as mentioned below:
In the previous approach The curr[] array is updated using 3 values only :

Value 1: curr[j] = prev[j-1] when str1[i-1] is equal to str2[j-1]
Value 2: curr[j] = prev[j] when str1[i-1] is not equal to str2[j-1]
Value 3: curr[j] = curr[j-1] when str1[i-1] is not equal to str2[j-1]

By keeping the track of these three values we can achiever our task using only a single 1-D array

Below is the code implementation of the approach:

C++
// A Space efficient Dynamic Programming
// based C++ program to find minimum
// number operations to convert str1 to str2
#include <bits/stdc++.h>
using namespace std;

class Solution {
public:
    // space optimization
    int editDistance(string str1, string str2)
    {
        int m = str1.size();
        int n = str2.size();
        int previous;
        vector<int> curr(n + 1, 0);

        for (int j = 0; j <= n; j++) {
            curr[j] = j;
        }
        for (int i = 1; i <= m; i++) {
            previous = curr[0];
            curr[0] = i;
            for (int j = 1; j <= n; j++) {
                int temp = curr[j];
                if (str1[i - 1] == str2[j - 1]) {
                    curr[j] = previous;
                }
                else {
                    curr[j] = 1
                              + min({ previous, curr[j - 1],
                                      curr[j] });
                }
                previous = temp;
            }
        }
        return curr[n];
    }
};

int main()
{
    string str1 = "GEEXSFRGEEKKS", str2 = "w3wiki";

    Solution ob;
    int ans = ob.editDistance(str1, str2);
    cout << ans << "\n";

    return 0;
}
Java
public class EditDistance {
    // This method calculates the edit distance (Levenshtein
    // distance) between two strings.
    public int editDistance(String str1, String str2)
    {
        // Get the lengths of the two input strings.
        int m = str1.length();
        int n = str2.length();

        // Initialize an array to store the current row of
        // edit distances.
        int[] curr = new int[n + 1];

        // Initialize the first row with values 0 to n.
        for (int j = 0; j <= n; j++) {
            curr[j] = j;
        }

        int previous;
        for (int i = 1; i <= m; i++) {
            // Store the value of the previous row's first
            // column.
            previous = curr[0];
            curr[0] = i;

            for (int j = 1; j <= n; j++) {
                // Store the current value before updating
                // it.
                int temp = curr[j];

                // Check if the characters at the current
                // positions in str1 and str2 are the same.
                if (str1.charAt(i - 1)
                    == str2.charAt(j - 1)) {
                    // If they are the same, no additional
                    // cost is incurred.
                    curr[j] = previous;
                }
                else {
                    // If the characters are different,
                    // calculate the minimum of three
                    // operations:
                    // 1. Deletion (previous value)
                    // 2. Insertion (current row's previous
                    // value)
                    // 3. Substitution (diagonal previous
                    // value)
                    curr[j] = 1 + Math.min(
                      Math.min(previous, curr[j - 1]), curr[j]);
                }
                // Update the previous value to the stored
                // temporary value.
                previous = temp;
            }
        }
        // The value in the last cell of the current row
        // represents the edit distance.
        return curr[n];
    }

    public static void main(String[] args)
    {
        String str1 = "GEEXSFRGEEKKS";
        String str2 = "w3wiki";

        EditDistance ed = new EditDistance();
        int ans = ed.editDistance(str1, str2);
        System.out.println(ans);
    }
}
Python3
def editDistance(str1, str2):
    # Get the lengths of the input strings
    m = len(str1)
    n = len(str2)

    # Initialize a list to store the current row
    curr = [0] * (n + 1)

    # Initialize the first row with values from 0 to n
    for j in range(n + 1):
        curr[j] = j

    # Initialize a variable to store the previous value
    previous = 0

    # Loop through the rows of the dynamic programming matrix
    for i in range(1, m + 1):
        # Store the current value at the beginning of the row
        previous = curr[0]
        curr[0] = i

        # Loop through the columns of the dynamic programming matrix
        for j in range(1, n + 1):
            # Store the current value in a temporary variable
            temp = curr[j]

            # Check if the characters at the current positions in str1 and str2 are the same
            if str1[i - 1] == str2[j - 1]:
                curr[j] = previous
            else:
                # Update the current cell with the minimum of the three adjacent cells
                curr[j] = 1 + min(previous, curr[j - 1], curr[j])

            # Update the previous variable with the temporary value
            previous = temp

    # The value in the last cell represents the minimum number of operations
    return curr[n]


# Driver Code
if __name__ == "__main__":
    str1 = "GEEXSFRGEEKKS"
    str2 = "w3wiki"

    ans = editDistance(str1, str2)
    print(ans)
C#
using System;

class GFG {
    // Function to calculate the minimum edit distance
    // between two strings
    static int EditDistance(string str1, string str2)
    {
        // Get the length of the first string
        int m = str1.Length;
        // Get the length of the second string
        int n = str2.Length;

        // Initialize an array to store the current row
        int[] curr = new int[n + 1];

        for (int j = 0; j <= n; j++) {
            // Initialize the first row with values from 0
            // to n
            curr[j] = j;
        }
        // Initialize a variable to store the previous value
        int previous = 0;

        for (int i = 1; i <= m; i++) {
            // Store the current value at the beginning of
            // the row
            previous = curr[0];
            // Update the first element of the current row
            curr[0] = i;

            for (int j = 1; j <= n; j++) {
                // Store the current value in a temporary
                // variable
                int temp = curr[j];

                if (str1[i - 1] == str2[j - 1]) {
                    // Characters are the same, no operation
                    // needed
                    curr[j] = previous;
                }
                else {
                    // Update the current cell with the
                    // minimum of the three adjacent cells
                    curr[j]
                        = 1
                          + Math.Min(previous,
                                     Math.Min(curr[j - 1],
                                              curr[j]));
                }
                // Update the previous variable with the
                // temporary value
                previous = temp;
            }
        }
        // The value in the last cell represents the minimum
        // number of operations
        return curr[n];
    }
    // Driver Code
    static void Main(string[] args)
    {
        string str1 = "GEEXSFRGEEKKS";
        string str2 = "w3wiki";
        // Calculate the edit distance
        int ans = EditDistance(str1, str2);
        Console.WriteLine(ans);
    }
}
JavaScript
function editDistance(str1, str2) {
    // Get the lengths of the input strings
    const m = str1.length;
    const n = str2.length;

    // Initialize an array to store the current row
    const curr = new Array(n + 1).fill(0);

    // Initialize the first row with values from 0 to n
    for (let j = 0; j <= n; j++) {
        curr[j] = j;
    }

    // Initialize a variable to store the previous value
    let previous = 0;

    // Loop through the rows of the dynamic programming matrix
    for (let i = 1; i <= m; i++) {
        // Store the current value at the beginning of the row
        previous = curr[0];
        curr[0] = i;

        // Loop through the columns of the dynamic programming matrix
        for (let j = 1; j <= n; j++) {
            // Store the current value in a temporary variable
            const temp = curr[j];

            // Check if the characters at the current positions in str1 and str2 are the same
            if (str1[i - 1] === str2[j - 1]) {
                curr[j] = previous;
            } else {
                // Update the current cell with the minimum of the three adjacent cells
                curr[j] = 1 + Math.min(previous, curr[j - 1], curr[j]);
            }

            // Update the previous variable with the temporary value
            previous = temp;
        }
    }

    // The value in the last cell represents the minimum number of operations
    return curr[n];
}

// Driver Code
const str1 = "GEEXSFRGEEKKS";
const str2 = "w3wiki";

const ans = editDistance(str1, str2);
console.log(ans);

Output
3

Time Complexity: O(M*N)
Auxiliary Space: O(N)

Edit Distance

Given two strings str1 and str2 of length M and N respectively and below operations that can be performed on str1. Find the minimum number of edits (operations) to convert ‘str1‘ into ‘str2‘.  

  • Operation 1 (INSERT): Insert any character before or after any index of str1
  • Operation 2 (REMOVE): Remove a character of str1
  • Operation 3 (Replace): Replace a character at any index of str1 with some other character.

Note: All of the above operations are of equal cost. 

Examples: 

Input:   str1 = “geek”, str2 = “gesek”
Output:  1
Explanation: We can convert str1 into str2 by inserting a ‘s’ between two consecutive ‘e’ in str2.

Input:   str1 = “cat”, str2 = “cut”
Output:  1
Explanation: We can convert str1 into str2 by replacing ‘a’ with ‘u’.

Input:   str1 = “sunday”, str2 = “saturday”
Output:  3
Explanation: Last three and first characters are same.  We basically need to convert “un” to “atur”.  This can be done using below three operations. Replace ‘n’ with ‘r’, insert t, insert a

Illustration of Edit Distance:

Let’s suppose we have str1=”GEEXSFRGEEKKS” and str2=”w3wiki”
Now to convert str1 into str2 we would require 3 minimum operations:
Operation 1: Replace ‘X‘ to ‘K
Operation 2: Insert ‘O‘ between ‘F‘ and ‘R
Operation 3: Remove second last character i.e. ‘K

Refer the below image for better understanding.

Recommended Practice

Similar Reads

Edit Distance using Recursion:

Subproblems in Edit Distance:...

Edit Distance Using Dynamic Programming (Memoization):

In the above recursive approach, there are several overlapping subproblems:Edit_Distance(M-1, N-1) is called Three times Edit_Distance(M-1, N-2) is called Two times Edit_Distance(M-2, N-1) is called Two times. And so on… So, we can use Memoization technique to store the result of each subproblems to avoid recalculating the result again and again. Below are the illustration of overlapping subproblems during the recursion....

Edit Distance Using Dynamic Programming (Bottom-Up Approach):

Use a table to store solutions of subproblems to avoiding recalculate the same subproblems multiple times. By doing this, if same subproblems repeated during, we retrieve the solutions from the table itself....

Edit Distance Using Dynamic Programming (Optimization in Space Complexity):

Optimized Space Complexity Solution: In the above bottom up approach we require O(m x n) space. Let’s take an observation and try to optimize our space complexity: To fill a row in DP array we require only one row i.e. the upper row. For example, if we are filling the row where i=10 in DP array then we require only values of 9th row. So we simply create a DP array of 2 x str1 length. This approach reduces the space complexity from O(N*M) to O(2*N)....

Edit Distance Using Dynamic Programming (Further Optimization in Space Complexity):

As discussed the above approach uses two 1-D arrays, now the question is can we achieve our task by using only a single 1-D array? The answer is Yes and it requires a simple observation as mentioned below:In the previous approach The curr[] array is updated using 3 values only : Value 1: curr[j] = prev[j-1] when str1[i-1] is equal to str2[j-1]Value 2: curr[j] = prev[j] when str1[i-1] is not equal to str2[j-1] Value 3: curr[j] = curr[j-1] when str1[i-1] is not equal to str2[j-1] By keeping the track of these three values we can achiever our task using only a single 1-D array...

Real-World Applications of Edit Distance:

Spell Checking and Auto-CorrectionDNA Sequence AlignmentPlagiarism DetectionNatural Language ProcessingVersion Control SystemsString Matching...

Contact Us