【自然语言处理】基础一、编辑距离

编辑距离是处理文本纠错时常用的一个方法,英文叫Edit Distance

(以下内容参考https://www.geeksforgeeks.org/edit-distance-dp-5/
给定两个字符串str1和str2,我们可以在str1上执行以下3种操作来讲str1调整成为str2:

  1. 插入
  2. 删除
  3. 替换

例如:

Input:   str1 = "geek", str2 = "gesek"
Output:  1
可以在"geek"之间插入 's'.

Input:   str1 = "cat", str2 = "cut"
Output:  1
可以将"cat"中的"a"替换为"u".

Input:   str1 = "sunday", str2 = "saturday"
Output:  3
由于str1和str2的头第一个字符"s"和尾三个字符"day"是一样的,所以只需要将"un"改编为"stur".
可以将"n"替换为"r",再在前面插入"st".

m: Length of str1 (first string)
n: Length of str2 (second string)
我们对于字符串的操作流程如下:
1、从两个字符串的最后一个字符开始,如果两个字符是一样的则什么也不做,转而比较接下来的m-1和n-1个字符。
2、最后两个字符如果不一样,则可以采用上述三种操作使之一样,使编辑距离+1,然后转而比较接下来的。

  • 插入:则比较str1剩下的m个字符和str2剩下的n-1个字符;
  • 删除:则比较str1剩下的m-1个字符和str2剩下的n个字符;
  • 替换:则比较str1剩下的m-1个字符和str2剩下的n-1个字符;
#c++
// A Naive recursive C++ program to find minimum number
// operations to convert str1 to str2
#include <bits/stdc++.h>
using namespace std;

// Utility function to find minimum of three numbers
int min(int x, int y, int z) { 
	return min(min(x, y), z);
 }

int editDist(string str1, string str2, int m, int n)
{
	// If first string is empty, the only option is to
	// insert all characters of second string into first
	if (m == 0)
		return n;

	// If second string is empty, the only option is to
	// remove all characters of first string
	if (n == 0)
		return m;

	// If last characters of two strings are same, nothing
	// much to do. Ignore last characters and get count for
	// remaining strings.
	if (str1[m - 1] == str2[n - 1])
		return editDist(str1, str2, m - 1, n - 1);

	// If last characters are not same, consider all three
	// operations on last character of first string,
	// recursively compute minimum cost for all three
	// operations and take minimum of three values.
	return 1
		+ min(editDist(str1, str2, m, n - 1), // Insert
				editDist(str1, str2, m - 1, n), // Remove
				editDist(str1, str2, m - 1,
						n - 1) // Replace
			);
}

int main()
{
	// your code goes here
	string str1 = "sunday";
	string str2 = "saturday";

	cout << editDist(str1, str2, str1.length(),
					str2.length());
	return 0;
}
#python
def editDistance(str1, str2, m, n):
	if m == 0:
		return n
		
	if n == 0:
		return m
		
	if str1[m-1] == str2[n-1]:
		return editDistance(str1, str2, m-1, n-1)
		
	return 1 + min(editDistance(str1, str2, m, n-1),
				editDistance(str1, str2, m-1, n),
				editDistance(str1, str2, m-1, n-1) )
str1 = "sunday"
str2 = "saturday"
print editDistance(str1, str2, len(str1), len(str2))

当然,上述的方法在某些情况下存在大量重复计算,这在很多DP问题中也出现过,解决方法可以在Edit Distance中参考。
代码如下:

# 基于动态规划的解法
def edit_dist(str1, str2):
    
    # m,n分别字符串str1和str2的长度
    m, n = len(str1), len(str2)
    
    # 构建二维数组来存储子问题(sub-problem)的答案 
    dp = [[0 for x in range(n+1)] for x in range(m+1)] 
      
    # 利用动态规划算法,填充数组
    for i in range(m+1): 
        for j in range(n+1): 
  
            # 假设第一个字符串为空,则转换的代价为j (j次的插入)
            if i == 0: 
                dp[i][j] = j    
              
            # 同样的,假设第二个字符串为空,则转换的代价为i (i次的插入)
            elif j == 0:
                dp[i][j] = i
            
            # 如果最后一个字符相等,就不会产生代价
            elif str1[i-1] == str2[j-1]: 
                dp[i][j] = dp[i-1][j-1] 
  
            # 如果最后一个字符不一样,则考虑多种可能性,并且选择其中最小的值
            else: 
                dp[i][j] = 1 + min(dp[i][j-1],        # Insert 
                                   dp[i-1][j],        # Remove 
                                   dp[i-1][j-1])      # Replace 
  
    return dp[m][n] 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值