编辑距离(LD)算法的python实现


每篇一句:

God made relatives.Thank God we can choose our friends. ——《加菲猫》


编辑距离算法简介:

  • 定义:
    设A和B是两个字符串。将字符串A转换为字符串B所用的最少字符操作数称为字符串A到字符串B的编辑距离。(这里所说的字符操作包括:删除一个字符,插入一个字符,修改一个字符)是由俄国科学家Levenshtein提出的,故又叫Levenshtein Distance 。(LD算法)

  • 基本性质:
    1.LD(A,A)=0

    2.LD(A,”“)=Len(A)

    3.LD(A,B)=LD(B,A)

    4.0≤LD(A,B)≤Max(Len(A),Len(B))

    5.LD(A,B)=LD(Rev(A),Rev(B))

    6.LD(A+C,B+C)=LD(A,B)

    7.LD(A+B,A+C)=LD(B,C)

    8.LD(A,B)≤LD(A,C)+LD(B,C)

    9.LD(A+C,B)≤LD(A,B)+LD(B,C)

    为了讲解计算LD(A,B), 给予一下几个定义:
    A=a1a2…aN,表示A是由a1a2…aN这N个字符组成,Len(A)=N
    B=b1b2…bN,表示B是由b1b2…bM这M个字符组成,Len(B)=M
    定义LD(i, j)=LD(a1a2…ai, b1b2…bj),其中0<=N, 0<=M
    故:

    • LD(N,M) = LD(A,B)
    • LD(0,0) = 0
    • LD(0,j) = j
    • LD(i,0) = i

    对于1<=i<=N, 1<=j<=M, 有公式一:
    若ai=bj, 则LD(i, j) = LD(i-1, j-1)
    若ai≠bj, 则LD(i, j) = Min(LD(i-1, j-1), LD(i-1, j), LD(i, j-1))+1

  • 简单例子:
    A=GGATCGA
    B=GAATTCAGTTA
    将较短字符串A置于矩阵左侧,较长字符串B置于矩阵上侧:
    第一步:根据公式一填充第一行结果

    GAATTCAGTTA
    01234567891011
    G1012345678910
    G2
    A3
    T4
    C5
    G6
    A7

    第二步:填充其他表格,取最右下角的数字即为编辑距离。

    GAATTCAGTTA
    01234567891011
    G1012345678910
    G211234566789
    A321123456788
    T432212345678
    C543322234567
    G654433333456
    A765444434455

python实现

具体解释说明见代码中注释

# coding=utf-8
# 这里的实现过程对算法进行了稍微的优化(运算结果应该稍快一些):首先计算两个字符串开头以及结尾
# 的共同字符子串,然后去掉相同部分,重新构造新字符串,减少迭代过程次数。
# 如:string_a = "GGATCGA" string_b = "GAATTCAGTTA"构造的新字符串为:
# new_a = "AATTCAGTT" new_b = "GATCG" 

def LD(string_a, string_b):
    diff_start = -1
    diff_end = -1
    len_a = len(string_a)
    len_b = len(string_b)
    short = min(len_a, len_b)

    # 寻找开头和结尾的共同字符串,并记录位置
    for i in range(0, short):
        if string_a[i] != string_b[i]:
            diff_start = i
            break
    if diff_start == -1:
        return abs(len_b - len_a)
    for i in range(0, short):
        if string_a[len_a - i -1] != string_b[len_b - i - 1]:
            diff_end = i
            break
    if diff_end == -1:
        return abs(len_b - len_a)

    # L(A+C, B+C) = LD(A, B)
    # 出去开头以及结尾相同的字符串,构建新的字符串
    long_str = unicode(string_a[diff_start: len_a - diff_end] if len_a >= len_b else string_b[diff_start: len_b - diff_end])
    short_str = unicode(string_a[diff_start: len_a - diff_end] if len_a < len_b else string_b[diff_start: len_b - diff_end])
    # print long_str
    # print short_str

    long_len = len(long_str)
    short_len = len(short_str)

    # store保存迭代过程中每次计算的结果
    store = range(0, long_len + 1)

    for i in range(short_len):
        temp = [i+1] * (long_len + 1)
        for j in range(long_len):
            if long_str[j] == short_str[i]:
                temp[j+1] = store[j]
            else:
                # 注意这时各个位置数据的对应关系
                temp[j+1] = min(store[j], store[j+1], temp[j]) + 1
        store = temp
        # print store
    # 最右下角即为编辑距离
    return store[-1]


# Test
string_a = "GGATCGA"
string_b = "GAATTCAGTTA"

ld = LD(string_a, string_b)
print ld

写在后面:

以上即为LD算法的基本内容以及python实现,如果有什么错误或者改进意见,欢迎在下面评论或着私信博主。
代码下载:码云-LD算法的python实现

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值