在机器翻译中,有时候要做句子的相似度比对,其中要用到编辑距离的计算。而网络上搜索到的资料大部分都将字符作为编辑距离计算的最小单位。事实上,对于句子来说,词语作为编辑距离的最小计算单位往往更加合理。通过动态规划的方法,我们能轻松实现编辑距离的计算。
这里要注意的是递推边界的问题。就是当待译句子移动完之后,会出现0-0,0-1,…,0-n的情况(n为候选句子包含词语的个数),这种情况下需要修改的次数我们可以知道分别是,0,1,….,n。同理假如候选句子经过删除之后,长度剩余为0,那么会出现0-0,1-0,2-0,…,m-0的匹配情况(m为待译句子包含词语的个数),这种情形下,修改次数为0,1,…,m。
因此在算法的开始要做一个数组的初始化,初始化这些已知的操作次数结果。
下面的代码中,我尝试写了递归和非递归的方法。
EditDistanceReverse是递归,EditDistance是非递归的方法。对于中文句子来说最好加入自定义的分词算法。理由我在一开始也说过了。
// EditDistance.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<string>
#include<iostream>
#include<vector>
using namespace std ;
int dist[100][100];
int EditDistance(const string pattern[], int pattern_size, const string candidate[], int candidate_size)
{
int r1 = 0;
int r2 = 0;
int r3 = 0;
int i,j;
//因为0-0编辑距离为0,0-1为1,依次类推
for(i = 0; i <= candidate_size; i++)
dist[0][i] = i;
for(i = 0; i <= pattern_size; i++)
dist[i][0] = i;
for (i = 1; i <= pattern_size; i++)
{
for (j = 1; j <= candidate_size; j++)
{
r1 = dist[i - 1][j] + 1;//删除
r2 = dist[i][j - 1] + 1;//插入
int delta = (pattern[i - 1] != candidate[j - 1] ? 1 : 0);
r3 = dist[i-1][j - 1] + delta;
int min = r1;
min = min > r2 ? r2 : min;
min = min > r3 ? r3 : min;
dist[i][j] = min;
}
}
return dist[pattern_size][candidate_size];
}
int EditDistanceCore(const string pattern[], int pattern_size, const string candidate[], int candidate_size)
{
int r1 = 0;
int r2 = 0;
int r3 = 0;
int i,j;
if(pattern_size == 0 || candidate_size == 0)
return dist[pattern_size][candidate_size];
if (!dist[pattern_size - 1][candidate_size])
dist[pattern_size - 1][candidate_size] = EditDistanceCore(pattern, pattern_size - 1, candidate, candidate_size);
r1 = dist[pattern_size - 1][candidate_size] + 1;//删除
if (!dist[pattern_size][candidate_size - 1])
dist[pattern_size][candidate_size - 1] = EditDistanceCore(pattern, pattern_size, candidate, candidate_size - 1);
r2 = dist[pattern_size][candidate_size - 1] + 1;//插入
int delta = (pattern[pattern_size - 1] != candidate[candidate_size - 1] ? 1 : 0);
if(!dist[pattern_size - 1][candidate_size - 1])
dist[pattern_size - 1][candidate_size - 1] = EditDistanceCore(pattern, pattern_size-1, candidate, candidate_size - 1);
r3 = dist[pattern_size - 1][candidate_size - 1] + delta;
int min = r1;
min = min > r2 ? r2 : min;
min = min > r3 ? r3 : min;
dist[pattern_size][candidate_size] = min;
return min;
}
int EditDistanceReverse(const string pattern[], int pattern_size, const string candidate[], int candidate_size)
{
int i,j;
//因为0-0编辑距离为0,0-1为1,依次类推
for(i = 0; i <= candidate_size; i++)
dist[0][i] = i;
for(i = 0; i <= pattern_size; i++)
dist[i][0] = i;
return EditDistanceCore(pattern, pattern_size, candidate, candidate_size);
}
int _tmain(int argc, _TCHAR* argv[])
{
string pattern[] ={"I","love","baby","me2"};
string candidate[] = { "I","love","me"};
cout << EditDistanceReverse(pattern, sizeof(pattern)/sizeof(string), candidate, sizeof(candidate)/sizeof(string));
//cout << EditDistance(pattern, sizeof(pattern)/sizeof(string), candidate, sizeof(candidate)/sizeof(string));
return 0;
}
原文地址:http://blog.csdn.net/lampqiu/article/details/46622241