加权无序字符串编辑距离

时间:2014-03-12 09:08:41

标签: algorithm edit-distance

我需要一种有效的方法来计算两个无序符号集合之间的最小编辑距离。就像Levenshtein距离(仅适用于序列)一样,我需要插入,删除和替换,每个符号成本不同。我也对恢复编辑脚本感兴趣。

由于我想要完成的与计算字符串编辑距离非常相似,我认为它可能被称为无序字符串编辑距离或者可能只是设置编辑距离。但是,谷歌没有发现任何搜索条件,所以我有兴趣了解这个问题是否为其他名称所知?

澄清一下,问题将通过

解决
def unordered_edit_distance(target, source):
    return min(edit_distance(target, source_perm) 
               for source_perm in permuations(source))

例如,unordered_edit_distance('abc', 'cba')0,而edit_distance('abc', 'cba')2。不幸的是,排列的数量变得非常快,即使对于中等大小的输入也不实用。

编辑更明确地说,操作与不同的费用相关联。

4 个答案:

答案 0 :(得分:1)

对它们进行排序(不必要),然后删除两组中相同(且数量相同!)的项目。 然后,如果集合大小相等,则需要更换数量;如果一个更大,那么你还需要一些插入或删除。无论如何,您需要的操作数量等于第一阶段后剩余的更大集合的大小。

答案 1 :(得分:1)

虽然你的观察是正确的,但你实际上是让一个简单的问题变得更加复杂。

由于源可以是原始源的任何排列,因此首先需要检查字符级别的差异。

每个地图都有两个地图计算目标和源字符串中单个字符的数量:

例如: a2 c:1 d:100

现在比较两张地图,如果你遗漏任何角色,你当然需要插入它,如果你有额外的角色,你可以删除它。而已。

答案 2 :(得分:1)

让我们暂时忽略替换。

现在,仅在第一组中确定元素(这将被视为删除)以及仅在第二组(将被视为插入)中的元素确定为一个相当微不足道的问题。这可以通过以下任一方式轻松完成:

  • 对集合进行排序并同时迭代两者,或
  • 将第一组中的每个元素插入到哈希表中,然后从哈希表中删除第二组中的每个元素,找不到每个元素都是插入,并且在我们完成之后每个元素都保留在哈希表中删除

现在,要包含替换,剩下的就是找到插入元素与已删除元素的最佳配对。这实际上是stable marriage problem

  

稳定婚姻问题(SMP)是在给定每个元素的一组偏好的情况下在两组元素之间找到稳定匹配的问题。匹配是从一组元素到另一组元素的映射。只要两种情况都不匹配,匹配就是稳定的:

     
      
  1. 第一个匹配集的某个给定元素A优先于已匹配A的元素上的第二个匹配集的某个给定元素B,并且
  2.   
  3. B也比B已经匹配的元素更喜欢A
  4.   

可以使用the Gale-Shapley algorithm来解决:

  

Gale-Shapley算法涉及许多“轮次”(或“迭代”)。在第一轮中,首先a)每个未受过教育的男人向他最喜欢的女人求婚,然后b)每个女人向她最喜欢的追求者回复“也许”,并且对所有其他追求者回答“不”。然后她暂时“订婚”到她最喜欢的求婚者,并且该求婚者同样暂时与她订婚。在随后的每一轮中,首先a)每个未被接纳的男人向他尚未提出的最优先的女性提出建议(无论女性是否已经参与),然后b)每个女人向她的追求者回复“也许”她最喜欢(无论是她现有的临时伴侣还是其他人)并且拒绝其他人(再次,也许包括她目前的临时伴侣)。约定的临时性质保留了已经参与的女性“交易”的权利(并且在此过程中,“直到当时的伙伴”为“jilt”)。

我们只需要确保成本。要将插入和删除配对,使其成为替换,我们将失去插入和删除的成本,并获得替换的成本,因此配对的净成本将为substitutionCost - insertionCost - deletionCost。 / p>

现在上面的算法保证所有插入或删除都会配对 - 我们不一定要这样,但是有一个简单的修复 - 只需创建一堆“保持原样”元素(在插入和删除上) ())任何与“保持原样”元素配对的插入或删除都会产生0的成本并导致它保持插入或删除状态,并且两个“原样保留”元素不会发生任何事情配对。

答案 3 :(得分:0)

关键观察:你只关心你的字符串中有多少'a','b',...,'z'或其他字母字符,因为你可以重新排列每个字符串中的所有字符。

因此,问题归结为以下几点:将s['a']个字符'a',s['b']个字符'b',...,s['z']个字符'z',转换为成t['a']个字符'a',t['b']字符'b',...,t['z']个字符'z'。如果您的字母表很短,s[]t[]可以是数组;通常,它们是从字母表到整数的映射,如C ++中的map <char, int>,Python中的dict等。

现在,对于每个字符c,您知道s[c]t[c]。如果s[c] > t[c],您必须从第一个无序字符串(s[c] - t[c])中删除c个字符s。如果s[c] < t[c],您必须将t[c] - s[c]个字符c添加到第二个无序字符串(t)。

X s[c] - t[c]为所有c的总和s[c] > t[c],您将获得必须从{{1}中删除的字符数} 总共。取s Y为所有t[c] - s[c]的{​​{1}}总和c,您将获得必须从s[c] < t[c]中删除的字符数

现在,让t。我们可以进行Z = min (X, Y)次替换,剩下的是Z次插入和X - Z次删除。因此,操作总数为Y - ZZ + (X - Z) + (Y - Z)