在网上看到一篇博客讲解Levenshtein的计算,大部分内容都挺好的,只是在一些细节上不够好,看了很长时间才明白。我对其中的算法描述做了一个简单的修改。原文的链接是:一个快速、高效的Levenshtein算法实现。
我修改的内容如下:
步骤 | 说明 |
1 | 设置n为字符串s的长度。(“GUMBO”) 设置m为字符串t的长度。(“GAMBOL”) 如果n等于0,返回m并退出。 如果m等于0,返回n并退出。 构造两个向量v0[m+1] 和v1[m+1] |
2 | 初始化 v0,内容为0,1,2,3,…,m,初始哈v1的第0个元素为0 |
3 | 检查s( i from 1 to n) 中的每个字符 |
4 | 检查t( j from 1 to m) 中的每个字符 |
5 | 如果 s[i] == t[j],则编辑代价cost = 0; 如果 s[i] != t[j],则编辑代价cost = 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]便是编辑距离的值。 |
代码示例如下:
1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 5 int LeastInThree(int a, int b, int c) { 6 return a>=b?(b>=c?c:b):(a>=c?c:a); 7 } 8 9 int CalcLevenshtein(char a[], char b[], int _aLen, int _bLen) { 10 int aLen = _aLen; 11 int bLen = _bLen; 12 if(aLen==0) { 13 return bLen; 14 } 15 else if(bLen==0) { 16 return aLen; 17 } 18 else { 19 int* V0 = new int[bLen+1]; 20 int* V1 = new int[bLen+1]; 21 int i = bLen; 22 int cost = 0; 23 // init the V0 24 while(i>=0) { 25 V0[i]=i; 26 i--; 27 } 28 // init the V1, but only the first element 29 V1[0]=0; 30 for(int j=1;j<=aLen;j++) { 31 for(int i=1;i<=bLen;i++) { 32 // check if inputA[i] equals to inputB[i] 33 // equal cost = 0; 34 // not cost = 1; 35 cost = a[j-1]==b[i-1]?0:1; 36 // 37 // V0[i-1]+cost V1[i-1]+1 38 // | 39 // | 40 // | 41 // | 42 // | 43 // | 44 // | 45 // V0[i]+1 ------ V1[i] 46 // distance from neighbor to V1[i], choose from 3 candidates 47 V1[i]=LeastInThree(V1[i-1]+1,V0[i]+1,V0[i-1]+cost); 48 } 49 int i=bLen; 50 while(i>=0) { 51 V0[i]=V1[i]; 52 i--; 53 } 54 V1[0]=V0[0]+1; 55 } 56 return V1[bLen]; 57 } 58 } 59 60 int main(int argc, char* argv[]) { 61 char inputa[] = "gumbo"; 62 char inputb[] = "gambol"; 63 cout<<CalcLevenshtein(inputa,inputb,strlen(inputa),strlen(inputb)); 64 return 0; 65 }