编辑距离 Edit Distance

编辑距离,即Levenshtein距离,衡量了两个字符串之间转换所需的最小编辑操作数。它广泛应用于DNA分析、拼写纠错、机器翻译和网址归类等领域。Levenshtein算法基于动态规划,通过构建二维矩阵确定字符串间的相似度。具体实现包括插入、删除和替换三种操作。Java和Python中都有相应的实现库,便于实际应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

编辑距离,又被称为Levenshtein距离,是指两个字符串之间,由其中一个转变成另一个所需的最小编辑操作次数。

比如:"sea" 转变为 "eat" 需要2次操作:

1、将 s 删除

2、在末尾添加 t

所以"sea"和"eat"两个字串的编辑距离为2。

这里需要注意的是:所谓的操作只包含 (1) 插入 (2) 删除 (3) 替换 ,并不包括字符的交换操作!

 

编辑距离的应用:

编辑距离可以表示两个字串的相似程度,编辑距离越小,两个字串相似度就越高。

1、DNA序列分析

2、拼写纠错

3、机器翻译

机器翻译通常使用的是Seq2seq模型。编辑距离可以作为Seq2seq的损失函数,即度量标记值和输出值之间的相似程度。

4、网址归类

性质相近的网站,它们的url地址通常也相似,比如csdn不同用户的网址。根据编辑距离可以有效地对网址进行大规模处理。

......

 

Levenshtein算法:

Levenshtein算法的本质其实是动态规划。以 "holiday" 和 "today" 为例,它的具体步骤是:

1、建立一个二维数组,大小为 (word1.length+1)*(word2.length+1)

  today
       
h      
o      
l      
i      
d      
a      
y      

2、将数组的第一行和第一列设定为0—n:

  today
 012345
h1     
o2     
l3     
i4     
d5     
a6     
y7     

这一步的本质其实是计算空字符转化为对应字符需要的操作次数。比如:matrix[0][0]=0代表空字符转空字符需要0次操作;matrix[1][0]=1代表空字符转"h"需要1次操作;matrix[2][0]=2代表空字符转"ho"需要两次操作……以此类推。


3、假设当前遍历到i、j,判断当前行对应的字母是否等于当前列对应的字母。如果相等,记操作代价cost=0;如果不等,记操作代价cost=1。然后matrix[i][j] = min( matrix[i-1][j]+1, matrix[i][j-1]+1, matrix[i-1][j-1]+cost )。

按照上述原则,最后得到完整的matrix为:

  today
 012345
h111234
o221234
l332234
i443334
d554344
a665434
y776543

matrix中的最后一个元素即为编辑距离!所以Edit_Distance( holiday, today ) = 3。


那么上述步骤到底在做些什么呢?我们来看一下结果:

  today
 012345
h111234
o221234
l332234
i443334
d554344
a665434
y776543

首先,假设蓝色部分是matrix[i][j],绿色部分matrix[i-1][j-1]代表由h转为t所需的操作,如果i行和j列对应的字母相等,那就说明新加一个字母不会引起操作次数的增加,所以cost=0,即matrix[i][j] = matrix[i-1][j-1]。"h" -> "t"需要1次操作,同时加上一个"o","ho" -> "to"同样只需要1次操作。

再看一下黄色的部分,假设黄色部分是matrix[i][j],显然matrix[i][j] = matrix[i][j-1]+1。matrix[i-1][j]+1 和 matirx[i][j-1]+1 的作用主要体现在当字符串长度不一样的时候,在图中,就是表示说会选择从"to"转变为"holid",而不是选择从"t"转变为"holid"。+1代表的意思就是在原来的基础上进行一次插入操作。

总体来看,其实就是一个动态规划的过程:matrix[i-1][j-1]、matrix[i-1][j] 和 matrix[i][j-1] 是到达 matrix[i][j] 的三条路径,而我们就是根据前一次状态,去选择能使当前状态最优的一条路径。

 

具体代码(Java):

public class Solution {
	
    //求nums数组中的最小值
    public static int Min(int[] nums) {
	int min = 100;
	for(int i:nums) {
		if(i < min) min = i;
	}
	return min;
    }
	

    public int minDistance(String word1, String word2) {
    	int[][] matrix = new int[word1.length()+1][word2.length()+1];
    	//初始化第一行和第一列
    	for(int i=0;i<matrix.length;i++) {
    		matrix[i][0] = i;
    	}
    	for(int i=0;i<matrix[0].length;i++) {
    		matrix[0][i] = i;
    	}
    	for(int i=0;i<word2.length();i++) {
    		char c2 = word2.charAt(i);
    		for(int j=0;j<word1.length();j++) {
    			char c1 = word1.charAt(j);
    			int cost = 0;
    			if(c1 != c2) cost = 1;
                        //状态转移方程
    			int[] nums = {matrix[j][i+1]+1,matrix[j+1][i]+1,matrix[j][i]+cost};
    			matrix[j+1][i+1] = Solution.Min(nums);
    		}
    	}
    	return matrix[word1.length()][word2.length()];
    }

}

 

Levenshtein在Python中的应用:

现在Levenshtein算法已经有现成的模块可以调用,所以在这里介绍一下python-Levenshtein,希望对大家在NLP领域的应用有所帮助。

首先需要安装Levenshtein相关包,安装语句如下:

pip install python-Levenshtein

下面是一些Levenshtein中具体的方法和应用:

http://nbviewer.jupyter.org/github/DiggerWang/Levenshtein/blob/master/Levenshtein.ipynb

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值