简介:编辑距离(Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。一般来说,编辑距离越小,两个串的相似度越大。在机器学习里面一般用word2vec或者神经网络来训练得到单词得相似度。
简单理解:量化两个字符串的相似度。
运用场景:
一般用于单词拼写检查。
算法原理:
比如 求a 和 ab之间得编辑距离。
空 | a | b | |
空 | 0 (从左空格到空格的操作) | 1(从左空格到字符a的操作,新增1个字符) | 2(从左空格到字符ab的操作,新增2个字符) |
a | 1 (从上空格到空格字母a的操作) |
图中表格的的数字代表其中的编辑距离。
空 | a | b | |
空 | 0 | 1 | 2 |
a | 1 | 0(上边的a与当前左边的a相似,所以操作0) |
空 | a | b | |
空 | 0 | 1 | 2 |
a | 1 | 0 | 1 |
红色的1计算公式:
红色0的最小编辑距离,计算距离来源于以下3个操作:
1、从上边b 的操作。(从b下面的2开始进行操作)
左边为空 上边为ab ,也是就 : 空 > ab
step1: 往下降一位。表达式左右边都要加一个a 则为 a 空 > a ab
step2: a ab 要与 ab 进行一个比较。
step3: 表达式左边需要删除一个a,左右才相等。操作为1。
2、从左边a的操作。
左边字符串 a 上边字符串为 a,
往右边移动一位, 左边为 a 右边为 ab
只需要新增一个字符串b,操作为1.
3、从左上角操作。
左边字符 空 上边字符 a, 空 > a
往斜角移动一位,只进行一个操作,若对左边字符进行操作的话,则往下移动一位, 相当于 上面 左边的空字符串 往下移动了一位. 左边字符 a 空 右边为 a a,
此时 aa 与 ab 进行一个比较, 需要替换掉一个a, 操作为1 .
以上为大体思路,当然也可以用递归树来理解:
比如两个字符串 mitcmu 和 mtacnu 的编辑距离:(i,j,edits)
在递归树中,每个节点代表一个状态,状态包含三个变量 (i, j, edist),其中,edist 表示处理到 a[i] 和 b[j] 时,已经执行编辑操作的次数。
在递归树中,(i, j) 两个变量重复的节点很多,比如 (3, 2) 和 (2, 3)。对于 (i, j) 相同的节点,我们只需要保留 edist 最小的,继续递归处理就可以了,剩下的节点都可以舍弃。所以,状态就从 (i, j, edist) 变成了 (i, j, min_edist),其中 min_edist 表示处理到 a[i] 和 b[j],已经执行的最少编辑次数。
代码:
private char[] a = "mitcmu".toCharArray();
private char[] b = "mtacnu".toCharArray();
private int n = 6;
private int m = 6;
private int minDist = Integer.MAX_VALUE; // 存储结果
// 调用方式 lwstBT(0, 0, 0);
public lwstBT(int i, int j, int edist) {
if (i == n || j == m) {
if (i < n) edist += (n-i);
if (j < m) edist += (m - j);
if (edist < minDist) minDist = edist;
return;
}
if (a[i] == b[j]) { // 两个字符匹配
lwstBT(i+1, j+1, edist);
} else { // 两个字符不匹配
lwstBT(i + 1, j, edist + 1); // 删除 a[i] 或者 b[j] 前添加一个字符
lwstBT(i, j + 1, edist + 1); // 删除 b[j] 或者 a[i] 前添加一个字符
lwstBT(i + 1, j + 1, edist + 1); // 将 a[i] 和 b[j] 替换为相同字符
}
}