原理
编辑距离是用来计算一个字符串(s1)变为另一个字符串(s2)所用的最小编辑操作次数(edit distance)。
编辑距离有好几种计算方式wiki详细介绍,这里介绍的是Levenshtein distance,这种计算方法只包含三种操作:
- 替换(substitution):将一个字符替换成另一个字符
- 插入(insertion):插入一个字符
- 删除(deletion):删除一个字符
举个栗子
比如: sduud转换为study
- 替换:sduud -> stuud
- 删除:stuud-> stu(u)d
- 插入:stud -> study
字符串sduud经过三步操作转换为study,所以编辑距离就是3。
计算公式
一般采用表格来展示编辑距离的计算过程,表格中每个元素计算公式:
t
a
b
[
i
,
j
]
=
m
i
n
(
t
a
b
[
i
−
1
,
j
]
+
1
,
t
a
b
[
i
,
j
−
1
]
+
1
,
t
a
b
[
i
−
1
,
j
−
1
]
+
f
(
i
,
j
)
)
tab[i,j] = min(tab[i-1,j]+1, tab[i,j-1]+1, tab[i-1,j-1]+f(i,j))
tab[i,j]=min(tab[i−1,j]+1,tab[i,j−1]+1,tab[i−1,j−1]+f(i,j))
其中,
- 当s1[i]==s2[j]时,f(i,j)=0;否则,f(i,j)=1。
- tab[i,j]表示的是表格中第i行,第j列所要填写的数字。
- 编辑距离就等于表格中右下角最后一个数字
我对这个公式的理解:表格中当前数=min(上边数+1,左边数+1,左上角数+f(i,j) )
图解计算过程
- 初始化表格第一行和第一列,这是为了解决字符串为空的情况,以及方便代码的实现。
- 根据公式计算表格中每个元素的结果,编辑距离就等于表格中右下角最后一个数字
实现代码
import numpy as np
def LevDistance(s1,s2):
len1=len(s1)+1
len2=len(s2)+1
#生成空的表格,并初始化第一行和第一列
tab = np.empty((len2,len1),dtype=np.int8)
tab[0,:]= range(len1)
tab[:,0]= range(len2)
#循环得到表格中的每个元素
for i in range(1,len2):
for j in range(1,len1):
fx=0 if s1[j-1]==s2[i-1] else 1
# 就是这个公式
tab[i,j] = min(tab[i-1,j]+1,tab[i,j-1]+1,tab[i-1,j-1]+fx)
return tab[-1,-1]
执行代码:
s1 = "sduud"
s2 = "study"
LevDistance(s1,s2)
输出结果(可以看出,表格中显示的结果和输出结果一致):
第三方库
import Levenshtein
Levenshtein.distance(s1,s2)
输出结果:
自己的理解,如有问题欢迎指正