1.什么是Levenshtein Distance
Levenshtein Distance,又称编辑距离,指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。levenshtein() 函数返回两个字符串之间的 Levenshtein 距离。编辑距离的算法是首先由俄国科学家Levenshtein提出的,故又叫Levenshtein Distance。
2.算法
步骤 | 说明 |
---|---|
1 | 设置n为字符串s的长度。("GUMBO") 设置m为字符串t的长度。("GAMBOL") 如果n等于0,返回m并退出。 如果m等于0,返回n并退出。 构造两个向量v0[m+1] 和v1[m+1],串联0..m之间所有的元素。 |
2 | 初始化 v0 to 0..m。 |
3 | 检查 s (i from 1 to n) 中的每个字符。 |
4 | 检查 t (j from 1 to m) 中的每个字符 |
5 | 如果 s[i] 等于 t[j],则编辑代价为 0; 如果 s[i] 不等于 t[j],则编辑代价为1。 |
6 | 设置单元v1[j]为下面的最小值之一: a、紧邻该单元上方+1:v1[j-1] + 1 b、紧邻该单元左侧+1:v0[j] + 1 c、该单元对角线上方和左侧+cost:v0[j-1] + cost |
7 | 在完成迭代 (3, 4, 5, 6) 之后,v1[m]便是编辑距离的值。 |
其中,cost为编辑代价,当字符相等时,为0,否则为1.
下面将演示如何计算"GUMBO"和"GAMBOL"两个字符串的Levenshtein距离
步骤1、2
| v0 | v1 | | | | |
| | G | U | M | B | O |
| 0 | 1 | 2 | 3 | 4 | 5 |
G | 1 | | | | | |
A | 2 | | | | | |
M | 3 | | | | | |
B | 4 | | | | | |
O | 5 | | | | | |
L | 6 | | | | | |
步骤3-6,当 i = 1
| v0 | v1 | | | | |
| | G | U | M | B | O |
| 0 | 1 | 2 | 3 | 4 | 5 |
G | 1 | 0 | | | | |
A | 2 | 1 | | | | |
M | 3 | 2 | | | | |
B | 4 | 3 | | | | |
O | 5 | 4 | | | | |
L | 6 | 5 | | | | |
步骤3-6,当 i = 2
| | v0 | v1 | | | |
| | G | U | M | B | O |
| 0 | 1 | 2 | 3 | 4 | 5 |
G | 1 | 0 | 1 | | | |
A | 2 | 1 | 1 | | | |
M | 3 | 2 | 2 | | | |
B | 4 | 3 | 3 | | | |
O | 5 | 4 | 4 | | | |
L | 6 | 5 | 5 | | | |
步骤3-6,当 i = 3
| | | v0 | v1 | | |
| | G | U | M | B | O |
| 0 | 1 | 2 | 3 | 4 | 5 |
G | 1 | 0 | 1 | 2 | | |
A | 2 | 1 | 1 | 2 | | |
M | 3 | 2 | 2 | 1 | | |
B | 4 | 3 | 3 | 2 | | |
O | 5 | 4 | 4 | 3 | | |
L | 6 | 5 | 5 | 4 | | |
步骤3-6,当 i = 4
| | | | v0 | v1 | |
| | G | U | M | B | O |
| 0 | 1 | 2 | 3 | 4 | 5 |
G | 1 | 0 | 1 | 2 | 3 | |
A | 2 | 1 | 1 | 2 | 3 | |
M | 3 | 2 | 2 | 1 | 2 | |
B | 4 | 3 | 3 | 2 | 1 | |
O | 5 | 4 | 4 | 3 | 2 | |
L | 6 | 5 | 5 | 4 | 3 | |
步骤3-6,当 i = 5
| | | | | v0 | v1 |
| | G | U | M | B | O |
| 0 | 1 | 2 | 3 | 4 | 5 |
G | 1 | 0 | 1 | 2 | 3 | 4 |
A | 2 | 1 | 1 | 2 | 3 | 4 |
M | 3 | 2 | 2 | 1 | 2 | 3 |
B | 4 | 3 | 3 | 2 | 1 | 2 |
O | 5 | 4 | 4 | 3 | 2 | 1 |
L | 6 | 5 | 5 | 4 | 3 | 2 |
步骤7
编辑距离就是矩阵右下角的值,v1[m] == 2。
3.代码实现
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
#define min(a,b) ((a<b)?a:b)
//算法
int ldistance(const string source, const string target)
{
//step 1
int n = source.length();
int m = target.length();
if (m == 0) return n;
if (n == 0) return m;
//Construct a matrix
typedef vector< vector<int> > Tmatrix;
Tmatrix matrix(n + 1);
for (int i = 0; i <= n; i++) matrix[i].resize(m + 1);
//step 2 Initialize
for (int i = 1; i <= n; i++) matrix[i][0] = i;
for (int i = 1; i <= m; i++) matrix[0][i] = i;
//step 3
for (int i = 1; i <= n; i++)
{
const char si = source[i - 1];
//step 4
for (int j = 1; j <= m; j++)
{
const char dj = target[j - 1];
//step 5
int cost;
if (si == dj){
cost = 0;
}
else{
cost = 1;
}
//step 6
const int above = matrix[i - 1][j] + 1;
const int left = matrix[i][j - 1] + 1;
const int diag = matrix[i - 1][j - 1] + cost;
matrix[i][j] = min(above, min(left, diag));
}
}//step7
return matrix[n][m];
}
void main(){
string s;
s = "ABC";
string d;
d = "abcd";
//cout << "source=";
//cin >> s;
//cout << "diag=";
//cin >> d;
int dist = ldistance(s, d);
cout << "dist=" << dist << endl;
system("pause");
}
参考资源:
http://www.cppblog.com/whncpp/archive/2008/09/21/62378.html
http://www.cnblogs.com/ymind/archive/2012/03/27/fast-memory-efficient-Levenshtein-algorithm.html
http://www.cnblogs.com/ac1985482/p/Levenshtein.html
http://baike.baidu.com/view/4123766.htm