编辑距离之动态规划算法

在自然语言处理中,经常需要比较段落句子之间的相似度,其中广泛使用的方法有空间向量模型、编辑距离方法。这里,重点说一下编辑距离算法,又叫Levenshtein距离。编辑距离的基本思想: 对于字符串A, 最少经过几次增、删、改操作可以变为字符串B, 其中操作的次数便是A和B之间的编辑距离。

如:

A:  aaabbb

B: aacb

需要把B中的c改为a,并在后面加入两个b, 因此其编辑距离为3。

上面的操作是针对于英文字符串的,对于汉字组成的句子,则需要把最小编辑单位确定为单个字。


求编辑距离可以使用动态规划的思想。

有字符串A(0...i), B(0...j)。 构建i+2行,j+2列的矩阵,对第一行依次赋值为0...j,  对第一列依次赋值为0...i。

依次对字符串A的0...i和B的0...j进行比较,并填充到矩阵中,其计算公式如下:

M[i][j] = Min(M[i-1][j]+1, M[i][j-1]+1, A[i]==B[j]?M[i-1][j-1]:M[i-1][j-1]+1)

这个递推式不难理解,既是在通过增加一个字符或修改一个字符间找到一个最小的最为当前求解问题的解。这样就可以一步一步求解子问题,最终得出问题的解。


算法Java程序如下:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
 * @author shao
 *
 */
public class Levenshtein {

	/**
	 * @param str1 待比较字符串1
	 * @param str2 待比较字符串2
	 * @return 编辑距离
	 * @description 计算编辑距离
	 */
	public static int getDistance(String str1, String str2){
		int len1 = str1.length();
		int len2 = str2.length();
		if(len1==0)
			return len2;
		else if(len2==0)
			return len1;
		
		int[][] disM = new int[len1+1][len2+1];
		for(int i=0;i<=len2;++i)
			disM[0][i] = i;
		for(int j=0;j<=len1;++j)
			disM[j][0] = j;
		for(int i=1;i<=len1;++i)
			for(int j=1;j<=len2;++j)
			{
				int top = disM[i-1][j]+1;
				int left = disM[i][j-1]+1;
				int lt = str1.charAt(i-1)==str2.charAt(j-1)?disM[i-1][j-1]:disM[i-1][j-1]+1;
				
				disM[i][j] = top


你可能感兴趣的:(自然语言处理)