Damerau–Levenshtein distance (Edit Distance with Transposition) c 实现
Posted
技术标签:
【中文标题】Damerau–Levenshtein distance (Edit Distance with Transposition) c 实现【英文标题】:Damerau–Levenshtein distance (Edit Distance with Transposition) c implementation 【发布时间】:2012-05-30 10:16:35 【问题描述】:我在 c++ 中实现了 Damerau-Levenshtein 距离,但它没有为输入(pantera,aorta)提供正确的 o/p,正确的 o/p 是 4,但我的代码给出了 5.....
int editdist(string s,string t,int n,int m)
int d1,d2,d3,cost;
int i,j;
for(i=0;i<=n;i++)
for(j=0;j<=m;j++)
if(s[i+1]==t[j+1])
cost=0;
else
cost=1;
d1=d[i][j+1]+1;
d2=d[i+1][j]+1;
d3=d[i][j]+cost;
d[i+1][j+1]=minimum(d1,d2,d3);
if(i>0 && j>0 && s[i+1]==t[j] && s[i]==t[j+1] ) //transposition
d[i+1][j+1]=min(d[i+1][j+1],d[i-1][j-1]+cost);
return d[n+1][m+1];
我没有看到任何错误。有人能找到代码的问题吗?
【问题讨论】:
不是在树上计算 leventhein 距离吗?你的树数据类型在哪里? 【参考方案1】:帖子中的算法不计算 Damerau-Levenshtein 距离。在wikipedia article 中,该算法被定义为最佳字符串对齐距离。
DL距离算法的java实现可以在另一个SO post找到。
要获得正确的 OSA 距离值,请将下面标有 -
的行更改为标有 +
的行
int editdist(string s,string t,int n,int m)
int d1,d2,d3,cost;
int i,j;
for(i=0;i<=n;i++)
for(j=0;j<=m;j++)
- if(s[i+1]==t[j+1])
+ if(s[i+1]==t[j+1])
cost=0;
else
cost=1;
d1=d[i][j+1]+1;
d2=d[i+1][j]+1;
d3=d[i][j]+cost;
d[i+1][j+1]=minimum(d1,d2,d3);
- if(i>0 && j>0 && s[i+1]==t[j] && s[i]==t[j+1] ) //transposition
+ if(i>0 && j>0 && s[i]==t[j-1] && s[i-1]==t[j] ) //transposition
d[i+1][j+1]=min(d[i+1][j+1],d[i-1][j-1]+cost);
return d[n+1][m+1];
看起来好像代码是从用编程语言编写的程序复制而来的,其中数组索引默认从 1 开始。因此,所有对距离数组d
的元素的引用都增加了。但是,对字符串中字符的引用是对基于 0 的数组的引用,因此不应更新它们。
要计算距离,必须正确初始化距离数组:
for( i = 0; i < n + 1; i++)
d[i][0] = i;
for( j = 1; j < m + 1; j++)
d[0][j] = j;
既然你得到了答案 5,你的距离数组可能已经正确初始化了。
由于上述算法不计算 DL 距离,这里是一个 C 语言实现的 DL 算法的草图(源自带有 java impl 的 SO 帖子。源自 Wikipedia 文章中的 ActionScript impl。)。
#define d(i,j) dd[(i) * (m+2) + (j) ]
#define min(x,y) ((x) < (y) ? (x) : (y))
#define min3(a,b,c) ((a)< (b) ? min((a),(c)) : min((b),(c)))
#define min4(a,b,c,d) ((a)< (b) ? min3((a),(c),(d)) : min3((b),(c),(d)))
int dprint(int* dd, int n,int m)
int i,j;
for (i=0; i < n+2;i++)
for (j=0;j < m+2; j++)
printf("%02d ",d(i,j));
printf("\n");
printf("\n");
return 0;
int dldist2(char *s, char* t, int n, int m)
int *dd;
int i, j, cost, i1,j1,DB;
int INFINITY = n + m;
int DA[256 * sizeof(int)];
memset(DA, 0, sizeof(DA));
if (!(dd = (int*) malloc((n+2)*(m+2)*sizeof(int))))
return -1;
d(0,0) = INFINITY;
for(i = 0; i < n+1; i++)
d(i+1,1) = i ;
d(i+1,0) = INFINITY;
for(j = 0; j<m+1; j++)
d(1,j+1) = j ;
d(0,j+1) = INFINITY;
dprint(dd,n,m);
for(i = 1; i< n+1; i++)
DB = 0;
for(j = 1; j< m+1; j++)
i1 = DA[t[j-1]];
j1 = DB;
cost = ((s[i-1]==t[j-1])?0:1);
if(cost==0) DB = j;
d(i+1,j+1) =
min4(d(i,j)+cost,
d(i+1,j) + 1,
d(i,j+1)+1,
d(i1,j1) + (i-i1-1) + 1 + (j-j1-1));
DA[s[i-1]] = i;
dprint(dd,n,m);
cost = d(n+1,m+1);
free(dd);
return cost;
【讨论】:
i hv 更改了你提到的行,但 pantera 和 aorta 的分析器仍然是 5,但正确的是 4。我在调用此函数的主要位置初始化了数组。 @user1413523 啊,对,这不是DL距离,而是wiki的最佳字符串对齐距离。可以在 SO post 中找到 DL 的 n 实现(在 java 中) 你的C版本有内存泄漏。DA
永远不会被释放。你甚至不需要 malloc 它,只需将它放在堆栈上。 int DA[256 * sizeof(int)]
。此外,如果您仍然想要 malloc,只需使用 calloc
,然后您可以跳过将所有 DA 设置为 0 的循环:calloc(256, sizeof(int))
。否则memset(DA, 0, sizeof(DA));
也可以使用(注意它必须在堆栈上,sizeof
才能正常工作。
@Joakim 在DA[256 * sizeof(int)]
中,* sizeof(int)
部分似乎是不必要的。您似乎没有使用256
以上的任何索引。应该只是DA[256]
恕我直言。
@GáborBakos 确实如此,我的想法有点太快了:)【参考方案2】:
这是我的这个算法的 C++ 版本:
int damerau_levenshtein_distance(std::string p_string1, std::string p_string2)
int l_string_length1 = p_string1.length();
int l_string_length2 = p_string2.length();
int d[l_string_length1+1][l_string_length2+1];
int i;
int j;
int l_cost;
for (i = 0;i <= l_string_length1;i++)
d[i][0] = i;
for(j = 0; j<= l_string_length2; j++)
d[0][j] = j;
for (i = 1;i <= l_string_length1;i++)
for(j = 1; j<= l_string_length2; j++)
if( p_string1[i-1] == p_string2[j-1] )
l_cost = 0;
else
l_cost = 1;
d[i][j] = std::min(
d[i-1][j] + 1, // delete
std::min(d[i][j-1] + 1, // insert
d[i-1][j-1] + l_cost) // substitution
);
if( (i > 1) &&
(j > 1) &&
(p_string1[i-1] == p_string2[j-2]) &&
(p_string1[i-2] == p_string2[j-1])
)
d[i][j] = std::min(
d[i][j],
d[i-2][j-2] + l_cost // transposition
);
return d[l_string_length1][l_string_length2];
【讨论】:
以上是关于Damerau–Levenshtein distance (Edit Distance with Transposition) c 实现的主要内容,如果未能解决你的问题,请参考以下文章