美文网首页
动态规划(2)——近似字符串的最小编辑距离

动态规划(2)——近似字符串的最小编辑距离

作者: 盛夏的風 | 来源:发表于2019-09-29 00:06 被阅读0次

    参考链接:https://www.cnblogs.com/jiabei521/p/3353390.html

    字符串的编辑距离也被称为距Levenshtein距离(Levenshtein Distance),属于经典算法,常用方法使用递归,更好的方法是使用动态规划算法,以避免出现重叠子问题的反复计算,减少系统开销。

    问题:找出字符串的编辑距离,即把一个字符串s1最少经过多少步操作变成编程字符串s2,操作有三种,添加一个字符,删除一个字符,修改一个字符。
    其实这个问题的关键是要求两个字符串的编辑距离
    例如 将aproxiomally一字转成approximatly:

    1、 approxiomally (null→p)插入
    2、approximally (o→null)删除
    3、approximatly (l→t)修改

    下面我们就针对这个问题来详细阐述一下:
    我们假定函数dist(str1, str2)表示字串str1转变到字串str2的编辑距离,那么对于下面3种极端情况,我们很容易给出解答(0表示空串)。

    1、dist(0, 0) = 0
    2、dist(0, s) = strlen(s)
    3、dist(s, 0) = strlen(s)
    

    对于一般的情况,dist(str1, str2)我们应该如何求解呢?

    假定我们现在正在求解dist(str1+char1, str2+char2),也就是把"str1+char1"转变成"str2+char2"。在这个转变过称中,我们要分情况讨论:

    1、 str1可以直接转变成str2。这时我们只要把char1转成char2就可以了(如果char1 != char2)。
    2、 str1+char1可以直接转变成str2。这时我们处理的方式是插入char2。
    3、str1可以直接转成str2+char2。这时的情况是我们需要删除char1。

    综合上面三种情况,dist(str1+char1, str2+char2)应该是三者的最小值。

    解析:

    首先定义这样一个函数——edit(i, j),它表示第一个字符串的长度为i的子串到第二个字符串的长度为j的子串的编辑距离。

    显然可以有如下动态规划公式:

    if i == 0 且 j == 0,edit(i, j) = 0
    if i == 0 且 j > 0,edit(i, j) = j
    if i > 0 且j == 0,edit(i, j) = i
    if i ≥ 1  且 j ≥ 1 ,edit(i, j) == min{ edit(i-1, j) + 1, edit(i, j-1) + 1, edit(i-1, j-1) + f(i, j) },当第一个字符串的第i个字符不等于第二个字符串的第j个字符时,f(i, j) = 1;否则,f(i, j) = 0。
    

    我们建立以下表格,将两个字符串按照表格1所示的样子进行摆放,规则按照以上公式进行输入,如下所示:

    计算edit(1, 1),edit(0, 1) + 1 == 1,edit(1, 0) + 1 == 1,edit(0, 0) + f(1, 1) == 0 + 0 == 0,min(edit(0, 1),edit(1, 0),edit(0, 0) + f(1, 1))==0,因此edit(1, 1) == 0。依次类推,有如下表格所示最终的矩阵:


    动态规划表

    此时右下角即为我们所需要的两个字符串的编辑距离。即字符串 "aproxiomally"和"approximatly"的编辑距离为3.

    有了以上的步骤,相信大家已经很清楚了,使用动态规划算法的时候,需要建立子问题的表格,以上的表格就是。而且我们能够很容易的使用二维数组建立。代码实现也就易如反掌了!

    以下是我的实现过程,希望对大家有用,如果有什么可以优化或者错误的地方,希望能够得到批评指正

    import numpy as np
    
    '''
    函数说明:计算近似字符串的逻辑距离
    parameter:
        str1
        str2
    return:
        distance
    '''
    
    def string_distance(str1,str2):
        m = str1.__len__()
        n = str2.__len__()
        distance = np.zeros((m+1,n+1))
    
        for i in range(0,m+1):
            distance[i,0]=i
        for i in range(0,n+1):
            distance[0,i]=i
        for i in range(1,m+1):
            for j in range(1,n+1):
                if str1[i-1]==str2[j-1]:
                    cost =0
                else:
                    cost=1
                distance[i,j]=min(distance[i-1,j]+1,distance[i,j-1]+1,distance[i-1,j-1]+cost)
        print(distance)
        return distance[m,n]
    
    
    
    if __name__=='__main__':
        a='aproxiomally'
        b='approximatly'
        result = string_distance(a,b)
        print(result)
    
    

    结果:


    最小编辑距离

    由图可知,与我们的动态规划表推出的结果一致。

    相关文章

      网友评论

          本文标题:动态规划(2)——近似字符串的最小编辑距离

          本文链接:https://www.haomeiwen.com/subject/qribuctx.html