【NLP】最小编辑距离

编辑距离

编辑距离又称Levenshtein距离,是指将一个字符串转为另一个字符串所需的字符编辑次数,包括以下三种操作:

  • 插入 - 在任意位置插入一个字符
  • 删除 - 将任意一个字符删除
  • 替换 - 将任意一个字符替换为另一个字符

最小编辑距离是指将一个字符串转为另一个字符串所需的最少字符编辑次数。

思路

计算最小编辑距离需要用到动态规划。对于两个字符串AABB,设f(i,j)f(i, j)表示将AA的前ii个字符构成的子串转为BB的前jj个字符构成的子串所需的最少次数,那么f(i,0)=if(i, 0) = if(0,j)=jf(0, j) = j,从AABB的最小编辑距离即f(m,n)f(m, n)mmnn分别为AABB的长度。
由于f(i,0)f(i, 0)f(0,j)f(0, j)已确定,可以考虑从f(i,j)f(i, j)递推到f(i+1,j)f(i+1, j)f(i,j+1)f(i, j+1)f(i+1,j+1)f(i+1, j+1),或者反过来,考虑从f(i1,j)f(i-1, j)f(i,j1)f(i, j-1)f(i1,j1)f(i-1, j-1)递推到f(i,j)f(i, j)。显然,前两种情况只需要在最后插入一个字符,即f(i,j)=f(i1,j)+1f(i, j) = f(i-1, j)+1f(i,j)=f(i,j1)+1f(i, j) = f(i, j-1)+1。而最后一种情况需要比较AA的第ii个字符和BB的第jj个字符,若相等,则f(i,j)=f(i1,j1)f(i, j) = f(i-1, j-1);否则需要进行替换操作,即f(i,j)=f(i1,j1)+1f(i, j) = f(i-1, j-1)+1。因此f(i,j)f(i, j)取三者最小值,递推公式为
f(i,j)=min{(f(i1,j)+1f(i,j1)+1f(i1,j1)+{0,A[i]=B[j]1,otherwise f(i,j) = min \begin{cases} (f(i-1, j)+1 \\ f(i, j-1)+1 \\ f(i-1, j-1)+ \begin{cases} 0, A[i] = B[j] \\ 1, otherwise \end{cases} \end{cases}

复杂度

时间复杂度和空间复杂度均为O(mn)O(mn),其中mmnn分别为AABB的长度。

Python代码

完整代码见Github

def Levenshtein(str1, str2):
  m = len(str1) + 1
  n = len(str2) + 1

  dp = [[0 for _ in range(n)] for _ in range(m)]
  for i in range(m):
    dp[i][0] = i
  for j in range(n):
    dp[0][j] = j

  for i in range(1, m):
    for j in range(1, n):
      if (str1[i-1] == str2[j-1]):
        dp[i][j] = dp[i-1][j-1]
      else:
        dp[i][j] = 1 + min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1])
  
  return dp[m-1][n-1]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章