【问题标题】:What are some algorithms for comparing how similar two strings are?有哪些算法可以比较两个字符串的相似程度?
【发布时间】:2013-02-24 13:35:26
【问题描述】:

我需要比较字符串以确定它们是否代表相同的事物。这与人类输入的案例标题有关,其中缩写和其他小细节可能有所不同。例如,考虑以下两个标题:

std::string first = "Henry C. Harper v. The Law Offices of Huey & Luey, LLP";

相对于:

std::string second = "Harper v. The Law Offices of Huey & Luey, LLP";

人类可以快速判断这些很可能是相同的。我目前采用的方法是通过将所有字母小写并删除所有标点符号和空格来规范化字符串:

std::string firstNormalized = "henrycharpervthelawofficesofhueylueyllp";

还有:

std::string secondNormalized = "harpervthelawofficesofhueylueyllp";

在这种情况下比较,一个是另一个的子序列,但您可以想象其他更复杂的变体,其中不一定会发生这种情况,但它们具有重要的共同子序列。偶尔也可能出现人为输入错误,例如转置字母和拼写错误。

也许某种字符差异程序可以提供帮助?我已经看到了用于比较要签入的代码差异的良好行差异程序,是否有类似的基于字符的东西,也许是在 boost 中?如果您可以计算共同的连续字符的数量并取非共享字符的比率,也许这将是一个很好的启发式方法?

最后,我需要一个布尔值来决定是否将它们视为相同。它不一定是完美的,但理想情况下应该很少出错。

我可以使用什么算法来量化这两个字符串彼此之间的相似程度,然后我可以通过一些启发式方法将其转换为是/否答案?

【问题讨论】:

标签: algorithm language-agnostic string-comparison stdstring heuristics


【解决方案1】:

你可以使用计算最长公共子序列长度的算法来解决这个问题。如果两个输入字符串的最长公共子序列的长度小于任何一个字符串的长度,则它们不相等。

如果你不想找出最长的公共子序列,你可以使用动态规划的方法来解决问题并优化空间复杂度。

【讨论】:

    【解决方案2】:

    您可以考虑的另一种算法是 Simon White Similarity:

    def get_bigrams(string):
        """
        Take a string and return a list of bigrams.
        """
        if string is None:
            return ""
    
        s = string.lower()
        return [s[i : i + 2] for i in list(range(len(s) - 1))]
    
    def simon_similarity(str1, str2):
        """
        Perform bigram comparison between two strings
        and return a percentage match in decimal form.
        """
        pairs1 = get_bigrams(str1)
        pairs2 = get_bigrams(str2)
        union = len(pairs1) + len(pairs2)
    
        if union == 0 or union is None:
            return 0
    
        hit_count = 0
        for x in pairs1:
            for y in pairs2:
                if x == y:
                    hit_count += 1
                    break
        return (2.0 * hit_count) / union
    

    【讨论】:

      【解决方案3】:

      Damerau Levenshtein distance 是另一种比较两个字符串的算法,它类似于 Levenshtein 距离算法。两者的区别在于它还可以检查字符之间的换位,因此可以提供更好的纠错结果。

      例如:nightnigth 之间的 Levenshtein 距离为 2 但 nightnigth 之间的 Damerau Levenshtein 距离将为 1,因为它只是一对字符的交换。

      【讨论】:

      • 请添加参考文献(网络、书籍、论文...)
      【解决方案4】:

      您可以为此使用 ngram。例如,将两个字符串转换为单词三元组(通常为小写),并比较它们彼此相等的百分比。

      您的挑战是定义相似度的最小百分比。

      http://en.wikipedia.org/wiki/N-gram

      【讨论】:

        【解决方案5】:

        您要查找的内容称为String Metric 算法。其中有大量,其中许多具有相似的特征。其中比较受欢迎:

        wiki page 上查看这些以及其他关于该主题的内容。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-04-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-20
          • 2018-03-08
          • 1970-01-01
          相关资源
          最近更新 更多