Levenshtein Distance 编辑距离

参考资料:
算法实现: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里面的前两个;可以变换最后一个相等,交给下一次去变化,最后一个相等的情况下,这里也可以不变。


Levenshtein Distance 编辑距离_第1张图片

自己实现的:

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()

你可能感兴趣的:(Levenshtein Distance 编辑距离)