我在 C++ 中使用 Levenshtein 距离算法来比较两个字符串以测量它们彼此之间的接近程度。但是,普通的 Levenshtein 距离算法不区分由空格分隔的单词边界。这导致距离计算比我想要的要小。我正在比较标题以查看它们彼此之间的接近程度,并且我希望算法不会将来自多个单词的字符计为匹配。
例如,如果我比较这两个字符串,我会得到以下结果,+
指定一个匹配项并-
指定一个不匹配项:
Al Chertoff Et
Al Church Department of finance Et
+++++------+--++-----++-+------+++
Al Ch e rt of f Et
我得到一个与"Chertoff"
四个单词匹配的单词的距离为 20,"Church Department of finance"
而我真的希望它们被认为彼此之间的距离更远,因为不允许字符与多个单词匹配,并且与单词的距离为 25"Chertoff"
最匹配一个单词"Department"
,三个字符匹配:
Al Chertoff Et
Al Church Department of finance Et
+++--------+--++---------------+++
Al e rt Et
Ch off
我如何调整 Levenshtein 距离来完成此任务,或者是否有另一种更适合此的距离算法?也许在每个单词上单独使用 Levenshtein 距离并选择距离最小的单词?但是,如果在字符串深处匹配一个单词会导致后续单词匹配不佳,因为它们的匹配最好在字符串的较早位置?这可以通过将 Levenshtein 距离调整为单词级别来以某种方式完成吗?
例如,对于以下更复杂的示例,此想法的最短距离是 20:
Al Chertoff Deport Et
Al Church Department of finance Et
+++++----++++-++---------------+++
Al Ch Dep rt Et
ertoff o
而不是最大化"Chertoff"
的匹配并获得 24 的更长距离:
Al Chertoff Deport Et
Al Church Department of finance Et
+++--------+--++-----+---------+++
Al e rt o Et
Ch off
Dep rt
我目前对 Levenshtein 距离的实现如下:
size_t
levenshtein_distance(const std::string& a_compare1,
const std::string& a_compare2) {
const size_t length1 = a_compare1.size();
const size_t length2 = a_compare2.size();
std::vector<size_t> curr_col(length2 + 1);
std::vector<size_t> prev_col(length2 + 1);
// Prime the previous column for use in the following loop:
for (size_t idx2 = 0; idx2 < length2 + 1; ++idx2) {
prev_col[idx2] = idx2;
}
for (size_t idx1 = 0; idx1 < length1; ++idx1) {
curr_col[0] = idx1 + 1;
for (size_t idx2 = 0; idx2 < length2; ++idx2) {
const size_t compare = a_compare1[idx1] == a_compare2[idx2] ? 0 : 1;
curr_col[idx2 + 1] = std::min(std::min(curr_col[idx2] + 1,
prev_col[idx2 + 1] + 1),
prev_col[idx2] + compare);
}
curr_col.swap(prev_col);
}
return prev_col[length2];
}