[Algorithm] Dynamic programming - 01 - Drawing 2-d matrix

发布时间 2023-03-28 14:31:43作者: Zhentiw

Problem: Levenshtein Distance

Write a function that takes in two strings and returns the minimum number of edit operations that need to be performed on the first string to obtain the second string. There are three edit operations: insertion of a character, deletion of a character, and substitution of a character for another.

str1 = "abc"
str2 = "yabd"
Sample Output
2 // insert "y"; substitute "c" for "d"

 

Code:

查看代码
 function minEditOps(str1, str2) {
  const m = str1.length;
  const n = str2.length;

  // Initialize a 2D array with zeros
  const dp = Array.from({ length: m + 1 }, () =>
    Array.from({ length: n + 1 }, () => 0)
  );

  // Fill in the first row and column with incremental values
  for (let i = 0; i <= m; i++) {
    dp[i][0] = i;
  }
  for (let j = 0; j <= n; j++) {
    dp[0][j] = j;
  }

  // Fill in the rest of the matrix using dynamic programming
  for (let i = 1; i <= m; i++) {
    for (let j = 1; j <= n; j++) {
      if (str1[i - 1] === str2[j - 1]) {
        dp[i][j] = dp[i - 1][j - 1];
      } else {
        dp[i][j] =
          1 +
          Math.min(
            dp[i - 1][j - 1], // substitution
            dp[i - 1][j], // deletion
            dp[i][j - 1] // insertion
          );
      }
    }
  }

  // The minimum number of edit operations is at the bottom right corner of the matrix
  return dp[m][n];
}

 

Drawing a 2-d matrix

   ''  y a b d
''  0  1 2 3 4  -> insertion
a   1  1 1 2 3
b   2  2 2 1 2
c   3  3 3 2 2

|              \
deletion         substitution

 

Looking at first row:

   ''  y a b d
''  0  1 2 3 4  -> insertion

From left to right, we repeatly ask the question

from '' (column)to '' (row), how many edits we need? 0

from '' (column)to 'y', how many edits we need? insert 'y'

from '' (column)to 'a', how many edits we need? based on current 'y', to 'ya', insert 'a'

from '' (column)to 'b', how many edits we need? based on current 'ya', to 'yab', insert 'b'

from '' (column)to 'd', how many edits we need? based on current 'yab', to 'yabd', insert 'd'

Every time we move one column, we use the result based on previou column, and operation we do is insertion.

 

Looking at first column

   '' 
''  0  
a   1 
b   2
c   3 

|              
deletion

from '' (column)to '' (row), how many edits we need? 0

from 'a' (column)to ''(row), how many edits we need? delete 'a'

from 'b' (column)to ''(row), how many edits we need?  already deleted 'a', nowdelete 'b'

from 'c' (column)to ''(row), how many edits we need?  already deleted 'ab', nowdelete 'c'

Every time, we move down one row, we do deletion

 

When column(a) equals row(a)

   ''  y a b d
''  0  1 2 3 4  -> insertion
a   1  1 1
b   2   
c   3   

|              \
deletion         substitution

For example, we reach column(a) and row(a), because they are the same, so we do need to do anything, the same as column('') and row('y')case. This operation is substitution.

 

When column and row are different

''  y a b d
''  0  1 2 3 4  -> insertion
a   1  1 1 2 3
b   2  2 2 1 2
c   3  3 3 2 ?

|              \
deletion         substitution

For example the ?

 1 2
 2 ?

We check the values and get min value then +1. so ? = 1 + 1 = 2