是什么?
编辑距离算法(Edit Distance),即Levenshtein Distance,用于计算一个单词转换到另一个单词的最短距离(其转换的三种方法:删、插、替),此概念在1965年由俄罗斯科学家 弗拉基米尔·莱文斯坦(Levenshtein · Vladimir)提出,故称Levenshtein Distance。
前言导入
如果我们想把单词cat变成单词cut,该怎样去做呢?答案显而易见,我们只需要把"a"替换成"u"。
但是,一旦遇到比较复杂的词,例如attention变成attitude,是不是需要几秒来观察了?正因如此,我们不妨让电脑帮我们来算一下
准备实践
现在,我们给定两个单词,word1和word2,使用编辑距离的概念去探寻到它们转换所需的最小操作数
示例:
string word1 = "aptitude"
string word2 = "attitude"
过程:
aptitude -> attitude(将"p"替换为"t")
最短距离:1
记住最关键的三个操作:
- 将一个字符替换成另外一个字符(
Substitutions
) - 插入一个字符(
Insertions
) - 删除一个字符(
Deletions
)
我们可以设置一个,这是什么意思呢?
例如我们要把Sun转换为Satur,既然要转换,就要取它们所有的字母,即Sun取前三个,Satur取前五个,此时我们可以表示成了,是不是清楚了i和j是什么作用?
Sun转换为Satur需要3次操作,将at插入在S和u之间,把n替换为r。
此时我们就可以表示为
那么的定义为:word1的前 i 个字符 与 word2的前 j 个字符 转换所需的最短距离。
接下来让我们分解一下它
第一种情况,也是比较乐观的情况,即word1与word2的末尾字符相同:
如果Word1的i-1与Word2的j-1是相同的,那么我们可以直接说 =
第二种情况没有这么乐观,即word1与word2的末尾字符不相同:
这样我们就要分类讨论了,也就是插,删,替三种方法
首先我们先来看看插入:
我们假设word1相较于word2,末尾只需要再添加一个Y,使之与后者相同
接下来是删除:
我们假设word1相较于word2,末尾需要去掉X,使得word1的i-1个字符与word2的j个字符有着较高相似性
最后是替换:
我们假设word1相较于word2,除去末尾有着高度的相似性,我们只需将X替换为Y,使得word1的i-1个字符与word2的j-1个字符有着较高相似性
这样,我们得出了三个结论:
插:
删:
替:
它们都是的值,我们要在其中选择最小值,所以可以表示为
是不是光看公式有些难以理解,让我们来使用可视化的观察。
我们先把它画成表格状的,根据我们上面得到的结论,可以画出一个:
第一种末尾相同的情况:
第二种不相同的情况:
再把它们套入上面的表格里面,是不是简单了很多?
首先,我们来看第一个格子,h和r不相等,取最小值,也就是左上角的0,完成了一次替换操作,所以次数加一
这样,每次都取最小值,遇到相等的取左上角数字不变,以此类推,我们可以得到这个图
最终右下角的数字即我们所要求的最短距离,我们可以验证一下是不是3次
可以看到,绿色的是实质性的操作,蓝色表示没有操作,因为它们是相同的。
这样,是不是就理解了呢?
代码部分
使用C++实现
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1000 + 5;
int d[maxn][maxn];
void LevenshteinDistance(string word1,string word2){
int len1 = word1.length();
int len2 = word2.length();
for (int i = 0; i <= len1; i++) {
d[i][0] = i;
}
for (int i = 0; i <= len2; i++) {
d[0][i] = i;
}
for (int i = 1; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1);
d[i][j] = min(d[i][j], d[i - 1][j - 1] + (word1[i - 1] != word2[j - 1]));
}
}
cout << d[len1][len2] << endl;
}
int main() {
string word1, word2;
cin >> word1 >> word2;
LevenshteinDistance(word1, word2);
return 0;
}
总结
编辑距离算法是一个古老却又十分有效的算法,可以在日常应用中帮助我们做许多事,可以用其计算字符串的相似度,这对一些查重来说是非常有用的
第一次写文章,本人才疏学浅,若有不足之处请见谅