【问题标题】:Is there an edit distance algorithm that takes "chunk transposition" into account?是否有考虑“块转置”的编辑距离算法?
【发布时间】:2009-05-18 14:44:34
【问题描述】:

我将“块转置”放在引号中,因为我不知道技术术语是否或应该是什么。只知道该过程是否有技术术语会非常有帮助。

Wikipedia article on edit distance 提供了一些关于这个概念的良好背景。

考虑到“块转置”,我的意思是

Turing, Alan.

应该匹配

Alan Turing

比匹配更接近

Turing Machine

即距离计算应该检测文本的子字符串何时在文本中简单地移动。常见的 Levenshtein 距离公式并非如此。

字符串最多只有几百个字符——它们是作者姓名或作者姓名列表,可以采用多种格式。我不做 DNA 测序(尽管我怀疑做过的人会对这个主题有所了解)。

【问题讨论】:

  • 您要比较哪种长度的字符串?我怀疑针对长文本的准确算法是不可行的。
  • 另外,这些“块”总是单词吗?
  • 如果“单词”是指“空格/标点分隔”,可能——但我想我不想依赖它。例如,我仍然希望 DiFranco 和 Di Franco 接近匹配,因为它们在编辑距离算法中。

标签: algorithm language-agnostic levenshtein-distance edit-distance


【解决方案1】:

对于您的应用程序,您可能应该考虑采用生物信息学中的一些算法。

例如,您可以首先通过确保所有分隔符都是空格或您喜欢的任何其他内容来统一您的字符串,这样您就可以将“Alan Turing”与“Turing Alan”进行比较。然后拆分其中一个字符串,并针对另一个字符串执行精确的字符串匹配算法(如Horspool-Algorithm),计算匹配子字符串的数量。

如果您想查找仅相似但不相等的匹配,则类似于 local alignment 的内容可能更合适,因为它提供了描述相似性的分数,但引用的 Smith-Waterman-Algorithm 是可能对您的应用程序来说有点矫枉过正,甚至不是可用的最佳局部对齐算法。

根据您的编程环境,可能已经有一个实现可用。我个人最近使用过SeqAn,这是一个用于 C++ 的生物信息学库,绝对提供了所需的功能。

嗯,这是一个相当抽象的答案,但我希望它为您指明正确的方向,但遗憾的是它没有为您提供解决问题的简单公式。

【讨论】:

    【解决方案2】:

    查看 Jaccard 距离度量 (JDM)。这是一个老的但很好的东西,非常擅长处理令牌级别的差异,例如姓氏在前,名字在后。对于两个字符串比较,JDM 计算只是两个字符串共有的唯一字符数除以它们之间的唯一字符总数(换句话说,联合上的交集)。例如,给定两个参数“JEFFKTYZZER”和“TYZZERJEFF”,分子为 7,分母为 8,得出的值为 0.875。我选择的字符作为标记并不是唯一可用的,顺便说一句,也经常使用 n-gram。

    【讨论】:

      【解决方案3】:

      编辑距离的最简单和最有效的现代替代方法之一称为归一化压缩距离,或 NCD。基本思想很容易解释。选择以您的语言实现的流行压缩器,例如 zlib。然后,给定字符串A和字符串B,令C(A)A和C(B)为B的压缩大小。令 AB 表示“AB 连接”,因此 C(AB) 表示“压缩后的大小“AB 连接”。接下来,计算分数

      (C(AB) - min(C(A),C(B))) / max(C (A), C(B))

      此值称为 NCD(A,B),它测量相似度类似于编辑距离,但支持更多形式的相似度,具体取决于您选择的数据压缩器。当然,zlib 支持您所描述的“块”样式相似性。如果两个字符串相似,则连接的压缩大小将接近每个单独的大小,因此分子将接近 0,结果将接近 0。如果两个字符串非常不同,则压缩后的大小将大致为添加的压缩大小,因此结果将接近 1。如果您已经可以访问 zlib 之类的数据压缩程序,则此公式比编辑距离或几乎任何其他显式字符串相似性度量更容易实现。这是因为启发式和优化等大部分“艰苦”工作已经在数据压缩部分完成,并且该公式仅使用与语言无关的通用信息理论提取其发现的相似模式的数量。此外,对于您描述的几百字节大小范围,此技术将比大多数显式相似性度量(例如编辑距离)快得多。有关此内容和示例实现的更多信息,只需搜索归一化压缩距离 (NCD) 或查看以下论文和 github 项目:

      http://arxiv.org/abs/cs/0312044 "压缩聚类"

      https://github.com/rudi-cilibrasi/libcomplearnC语言实现

      在过去十年中,还有许多其他关于此主题的实现和论文,您也可以使用其他语言并进行修改。

      【讨论】:

        【解决方案4】:

        我认为您正在寻找 Jaro-Winkler distance,这正是名称匹配。

        【讨论】:

        • 这似乎是字符转置而不是字符序列转置。在我的用例中,名称拼写正确的可能性要比单词顺序一致的可能性大。
        • 虽然它确实允许多个换位,但你是对的,它没有明确说明顺序。也许您可以尝试将这个相关的 SO 问题中的单词序列转换为字符的建议:http;//stackoverflow.com/questions/828132/levenshtein-distance-how-to-better-handle-words-swapping-positions
        【解决方案5】:

        您可能会发现压缩距离对此很有用。见an answer I gave for a very similar question

        或者您可以使用基于 k 元组的计数系统:

        1. 选择较小的 k 值,例如k=4。
        2. 将字符串的所有长度为 k 的子字符串提取到一个列表中。
        3. 对列表进行排序。 (O(knlog(n) 时间。)
        4. 对要比较的其他字符串执行相同操作。您现在有两个排序列表。
        5. 计算两个字符串共享的 k 元组的数量。如果字符串的长度为 n 和 m,则可以使用列表合并在 O(n+m) 时间内完成,因为列表是按排序顺序排列的。
        6. 共同的 k 元组数就是您的相似度得分。

        对于小字母表(例如 DNA),您通常会维护一个向量来存储每个可能的 k 元组的计数,而不是一个排序列表,尽管当字母表是任何字符时这是不切实际的——对于 k=4,你需要一个 256^4 的数组。

        【讨论】:

          【解决方案6】:

          我不确定您真正想要的是编辑距离——它仅适用于字符串——或语义距离——选择最合适或相似的含义。您可能想查看information retrieval 中的主题,了解如何区分给定特定术语或短语的最合适的匹配术语/短语。从某种意义上说,您正在做的是比较非常短的文档而不是字符串。

          【讨论】:

          • 问题在于我想将其用作自动分类器,而不是用作交互式查询建议设备。另外,我的主要用例(相同的单词,不同的词序和标点符号)是一个简单的编辑,例如在 Emacs 中对 transpose-words 的一次调用。 :)
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-12-31
          • 2015-12-09
          • 2010-11-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-13
          相关资源
          最近更新 更多