编辑距离

NLP中有个 编辑距离 的概念,常运用到单词纠错中。本博文介绍并代码实现 编辑距离。参考并综合以下三篇博文。

  • https://blog.csdn.net/LWHGMAN/article/details/100067314 
  • https://blog.csdn.net/baodream/article/details/80417695 
  • https://www.jianshu.com/p/a617d20162cf

编辑距离_第1张图片

 

代码思路 

# 1)首先考虑A串的第一个字符
#
#   假设存在两个字符串A和B,他们的长度分别是lenA和lenB。首先考虑第一个字符,由于他们是一样的,所以只需要计算A[2...lenA]和B[2...lenB]之间的距离即可。
# 那么如果两个字符串的第一个字符不一样怎么办?可以考虑把第一个字符变成一样的(这里假设从A串变成B串):
#
# 修改A串的第一个字符成B串的第一个字符,之后仅需要计算A[2...lenA]和B[2...lenB]的距离即可;
# 删除A串的第一个字符,之后仅需要计算A[2...lenA]和B[1...lenB]的距离即可;
# 把B串的第一个字符插入到A串的第一个字符之前,之后仅需要计算A[1...lenA]和B[2...lenB]的距离即可。

# 2)接下来考虑A串的第i个字符和B串的第j个字符。
#
#   我们这个时候不考虑A的前i-1字符和B串的第j-1个字符。如果A串的第i个字符和B串的第j个字符相等,即A[i]=B[j],则只需要计算A[i...lenA]和B[j...lenB]之间的距离即可。如果不想等,则:
#
# 修改A串的第i个字符成B串的第j个字符,之后仅需要计算A[i+1...lenA]和B[j+1...lenB]的距离即可;
# 删除A串的第i个字符,之后仅需要计算A[i+1...lenA]和B[j...lenB]的距离即可;
# 把B串的第j个字符插入到A串的第i个字符之前,之后仅需要计算A[i...lenA]和B[j+1...lenB]的距离即可。

#   写到这里,自然会想到用递归求解或者动态规划求解,由于用递归会产生很多重复解,所以用动态规划。

 递归代码:

oldarr=list('kittenkitten')
newarr=list('sittingsitting')
def fun(arrA,arrB,i,j):
    if i ==len(arrA) or j==len(arrB):
        return len(arrA)+len(arrB)-i-j
    else:
        if arrA[i]==arrB[j]:
            return fun(arrA,arrB,i+1,j+1)
        else:
            return min(fun(arrA,arrB,i+1,j)+1,fun(arrA,arrB,i,j+1)+1,fun(arrA,arrB,i+1,j+1)+1)  #删除 插入 替换

print fun(oldarr,newarr,0,0)

动态规划代码:

#动态规划
# 关键在于建立二维矩阵,这时,要分清i和j分别代表什么含义。矩阵中的数字,代表什么含义。
# 总结:i和j代表两个可以相对遍历的序列长度,矩阵中的数字代表目标函数的值。
#比如:i=1 和j=2时候,表示old序列只考虑到长度是1,而目标序列,假设只考虑到长度是2
oldarr=list('kittenkitten')
newarr=list('sittingsitting')

def funDynamic(oldarr,newarr):
    arrValue = []
    lenI = len(oldarr) + 1
    lenJ = len(newarr) + 1
    for i in range(lenI):
        arrValue.append([0] * lenJ)
    for i in range(lenI):
        for j in range(lenJ):
            if i==0 or j==0:
                arrValue[i][j] = i+j
                continue
            if oldarr[i-1]==newarr[j-1]:
                d = 0
            else:
                d = 1
                
            # 分别对应:插入、删除、替换 操作
            arrValue[i][j] =min(arrValue[i - 1][j] + 1, arrValue[i][j-1] + 1, arrValue[i-1][j-1] + d)
    for i in range(lenI):
        print arrValue[i]
    print arrValue[lenI-1][lenJ-1]

funDynamic(oldarr,newarr)

 

你可能感兴趣的:(nlp)