定义
编辑距离又称Leveinshtein距离,是由俄罗斯科学家Vladimir Levenshtein在1965年提出。将源字符串转化为目标字符串所需要付出的代价,代价越低相似度越高,代价越高相似度越低。通常可以选择的方式为插入、替换、删除。公式如下: 其中LDa,b(i,j)表示长度为 i 的字符串 a 和长度为 j 的字符串 b 之间距离编辑所需要付出的代价。
举例
这里以Meng和man 2个字符串为例,进行相似度计算,根据公式,来推演以下是如何计算的。
1、初始化
在矩阵的第一行的时候表示 b 的长度为0,根据公式, b 的长度为0的时候,a 的编辑距离就是a的字符串长度,反之 b 的字符串长度也是如此。
如此迭代,可以最终得到矩阵
所以最后的编辑距离就是3
2、算法实现
public int editdistance (String str1,String str2) {
int n = str1.length();
int m = str2.length();
int d[][] = new int[n + 1][m + 1];
// 初始化第一列
for (int i = 0; i <= n; i++) {
d[i][0] = i;
}
// 初始化第一行
for (int j = 0; j <= m; j++) {
d[0][j] = j;
}
// 遍历str1
for (int i = 1; i <= n; i++) {
char ch1 = str1.charAt(i - 1);
// 去匹配str2
for (int j = 1; j <= m; j++) {
char ch2 = str2.charAt(j - 1);
int temp;
if (ch1 == ch2) {
temp = 0;
} else {
temp = 1;
}
// 左边+1,上边+1, 左上角+temp取最小
d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + temp);
}
}
return d[n][m];
}
private static int min(int one, int two, int three) {
int min = one;
if (two < min) {
min = two;
}
if (three < min) {
min = three;
}
return min;
}
复杂度分析: 当i<j的时候最小的时间复杂度是O(i^2),空间复杂度是O(i * j)
3、算法改进
在上面推演矩阵的时候发现没有必要记录整个矩阵的值,我只需要记录上一行的矩阵值和当前行的矩阵值。如此空间复杂度就从O(i * j)变成了O(2 * i)
4、改进算法实现
public int editdistance (String str1,String str2) {
if(str1.length() > str2.length()) {
String tmp = str1;
str1 = str2;
str2 = tmp;
}
int x,y,gap = 0;
if(str2.length() == str1.length()) {
x = str1.length();
y = x;
} else {
x = str1.length()+1;
y = str1.length();
gap = str2.length() - str1.length() -1;
}
int[] pre = new int[ y + 1];
int[] cur = new int[ y + 1];
for (int i = 0; i < pre.length; i++) {
pre[i] = i;
}
for (int i = 1; i <= x; i++) {
cur[0] = i;
for (int j = 1; j <= y; j++) {
if (str2.charAt(i - 1) == str1.charAt(j - 1)) {
cur[j] = pre[j - 1];
} else {
cur[j] = Math.min(cur[j - 1], Math.min(pre[j], pre[j - 1])) + 1;
}
}
int[] tmp = pre;
pre = cur;
cur = tmp;
}
return pre[pre.length - 1]+gap;
}
欢迎关注我的公众号
本文由博客群发一文多发等运营工具平台 OpenWrite 发布