句子相似度-编辑距离、余弦距离、杰卡德相似性
参考:http://www.cnblogs.com/biyeymyhjob/archive/2012/09/28/2707343.html http://www.cnblogs.com/pandora/archive/2009/12/20/levenshtein_distance.html
简介与描述:
编辑距离,又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。
例如将kitten一字转成sitting:
- sitten (k→s)
- sittin (e→i)
- sitting (→g)
俄罗斯科学家Vladimir Levenshtein在1965年提出这个概念。
问题:找出字符串的编辑距离,即把一个字符串s1最少经过多少步操作变成编程字符串s2,操作有三种,添加一个字符,删除一个字符,修改一个字符
解析:
首先定义这样一个函数——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。
计算编辑距离PYthon版
# -*- coding: utf-8 -*- def distacal(s1,s2):#计算编辑距离 m = len(s1) n = len(s2) colsize, matrix = m + 1, [] for i in range((m + 1) * (n + 1)): matrix.append(0) for i in range(colsize): matrix[i] = i for i in range(n + 1): matrix[i * colsize] = i for i in range(n + 1)[1:n + 1]: for j in range(m + 1)[1:m + 1]: if s1[j - 1] == s2[i - 1]: cost = 0 else: cost = 1 minValue = matrix[(i - 1) * colsize + j] + 1 if minValue > matrix[i * colsize + j - 1] + 1: minValue = matrix[i * colsize + j - 1] + 1 if minValue > matrix[(i - 1) * colsize + j - 1] + cost: minValue = matrix[(i - 1) * colsize + j - 1] + cost matrix[i * colsize + j] = minValue return matrix[n * colsize + m] distance = distacal("你说你是谁","我不知道你是谁") print distance
程序(C++):注意二维数组动态分配和释放的方法!!
#include <iostream> #include <string> using namespace std; int min(int a, int b) { return a < b ? a : b; } int edit(string str1, string str2) { int max1 = str1.size(); int max2 = str2.size(); int **ptr = new int*[max1 + 1]; for(int i = 0; i < max1 + 1 ;i++) { ptr[i] = new int[max2 + 1]; } for(int i = 0 ;i < max1 + 1 ;i++) { ptr[i][0] = i; } for(int i = 0 ;i < max2 + 1;i++) { ptr[0][i] = i; } for(int i = 1 ;i < max1 + 1 ;i++) { for(int j = 1 ;j< max2 + 1; j++) { int d; int temp = min(ptr[i-1][j] + 1, ptr[i][j-1] + 1); if(str1[i-1] == str2[j-1]) { d = 0 ; } else { d = 1 ; } ptr[i][j] = min(temp, ptr[i-1][j-1] + d); } } cout << "**************************" << endl; for(int i = 0 ;i < max1 + 1 ;i++) { for(int j = 0; j< max2 + 1; j++) { cout << ptr[i][j] << " " ; } cout << endl; } cout << "**************************" << endl; int dis = ptr[max1][max2]; for(int i = 0; i < max1 + 1; i++) { delete[] ptr[i]; ptr[i] = NULL; } delete[] ptr; ptr = NULL; return dis; } int main(void) { string str1 = "sailn"; string str2 = "failing"; int r = edit(str1, str2); cout << "the dis is : " << r << endl; return 0; }