参考资料:
算法实现:Levenshtein Distance, in Three Flavors
原理:wiki-Levenshtein distance
该距离是俄罗斯科学家Vladimir Levenshtein在1965年发明的,也叫做编辑距离(实际上编辑距离代表一大类算法),距离代表着从s到t需要删、插、代替单个字符的最小步骤数。
主要应用:
- Spell checking 检查拼写
- Speech recognition 语音识别
- DNA analysis DNA分析
- Plagiarism detection 检测抄袭
主要原理(理解下面的公式):
ai跟bj之间的变化差距可以有很多种方法,这里限定最后一个字符ai和bj最后一个变化。可以删除其中一个,然后交给下一次去变化,这里包含了min里面的前两个;可以变换最后一个相等,交给下一次去变化,最后一个相等的情况下,这里也可以不变。
自己实现的:
import my_common
@my_common.print_result_after
def levenshtein_distance(str1,str2):
matrix_width = len(str1) + 1
matrix_height = len(str2) + 1
matrix = [[0] * matrix_width for i in range(matrix_height)]
# 初始化
for i in range(matrix_width):
matrix[0][i] = i
for j in range(matrix_height):
matrix[j][0] = j
for i in range(1, matrix_height):
for j in range(1, matrix_width, ):
if str1[j - 1] == str2[i - 1]:
cost = 0
else:
cost = 1
try:
a = matrix[i - 1][j] + 1
b = matrix[i][j - 1] + 1
c = matrix[i - 1][j - 1] + cost
matrix[i][j] = min(a, b, c)
except Exception as e:
print(e)
print('{}-{}'.format(i, j))
print(matrix)
return matrix[-1][-1]
# 递归版本
@my_common.print_result_after
def levenshtein_distance2(str1,str2):
width = len(str1) + 1
height = len(str2) + 1
mat = [[-1]*width for _ in range(height)]
def levenshtein_distance2_1(i, j):
# 这个是为了递归的时候避免重复计算
if mat[i][j] != -1:
return mat[i][j]
if i == 0:
mat[i][j] = j
elif j == 0:
mat[i][j] = i
else:
if str2[i-1] == str1[j-1]:
cost = 0
else:
cost = 1
mat[i][j] = min(levenshtein_distance2_1(i-1,j)+1, levenshtein_distance2_1(i,j-1) + 1,
levenshtein_distance2_1(i - 1, j - 1) + cost)
return mat[i][j]
levenshtein_distance2_1(height-1,width-1)
print(mat)
return mat[-1][-1]
def main():
str1 = 'hello'
str2 = 'ello'
# [[0, 1, 2, 3, 4, 5], [1, 1, 1, 2, 3, 4], [2, 2, 2, 1, 2, 3], [3, 3, 3, 2, 1, 2], [4, 4, 4, 3, 2, 1]]
# 1
levenshtein_distance2(str1,str2)
if __name__ == '__main__':
main()