准确计算两篇文章之间的距离

时间:2013-01-20 16:58:05

标签: php algorithm levenshtein-distance

我正在编写一个软件来比较文章。我正在寻找一种有效而准确的算法来计算两篇文章之间的差异(变化)。变化应完全取决于单词而不是字母。我已经尝试了levenshtein(),但它的时间复杂度为 O(n * m),这在文章等大文本上执行时非常昂贵。我还试过similar_text(),其时间复杂度高于 O(n * m * 3)。此外,levenshtein()similar_text()计算将一个字符串转换为另一个字符串所需的操作数,这不是计算两篇大文章之间差异的准确方法。

我还有其他选择吗?

<小时/> 修改

我正试图从搜索引擎(Google)的角度大致计算出变化。

5 个答案:

答案 0 :(得分:1)

PostgreSQL使用tsvector进行全文搜索功能。也许这对你来说非常方便。

答案 1 :(得分:1)

如果您可以定义如何根据单词测量文本相似度,那么您就完成了一半。例如:您可以计算两篇文章中每个单词的出现次数,然后创建两个列表的简单差异。但是,这不符合意义相似性。

如果您有数据库,请使用其全文功能。如前所述,PostGres提供了这样的功能。我使用MSSQL,您可以简单地调用FREETEXT函数,该函数将计算一个'rank',表示两个文本的相似程度。

我强烈建议您使用成熟的产品,而不是尝试自己编写产品。

答案 2 :(得分:1)

无法比较两篇文章。 levenshtein()similar_text()旨在比较两个单词,而不是文章。

最简单的算法是用文字来爆炸你的文章,逐字逐句地找到相似的东西并做一些数学运算,这取决于你的任务,如下:

// not tested!
function similar_articles($articleA, $articleB) {
  $wordsA = array_unique(preg_split('@[\W]+@', $articleA));
  $wordsB = array_unique(preg_split('@[\W]+@', $articleA));
  $resultSimilarity = 0;
  foreach($wordsA as $wordA) {
    $wordSimilarity = 0;
    foreach($wordsB as $wordB) {
      similar_text($wordA, $wordB, $percent);
      $wordSimilarity = max($wordSimilarity, $percent);
    }
    $resultSimilarity += $wordSimilarity;
  }
  return($resultSimilarity / count($wordsA));
}

注意:similar_articles($artileA, $articleB)!= similar_articles($artileB, $articleA)因为similar_text($wordA, $wordB)!= similar_text($wordB, $wordA)

答案 3 :(得分:0)

计算距离类型的简单方法是比较参考。另一种方法是根据字典选择一些关键词,并按社会相关性的顺序计算距离。

另外,为了使用Levenshtein distance,请查看stringmetric

答案 4 :(得分:0)

就我而言,我需要计算两篇文章之间的差异。所以,我发现非常简单的解决方案非常适合我。它的工作原理是简单地将相似度计算为两篇文章之间的常用词除以 max(文章A中的词数,文章B中的词数) 即可。然后通过从100减去相似性来计算变化以获得变化百分比。下面的代码解释了这一切。

function get_variation($article1,$article2){

      $wordsA = array_unique(preg_split('@[\W]+@', $article1));
      $wordsB = array_unique(preg_split('@[\W]+@', $article2));
      $intersection = array_intersect($wordsA, $wordsB);
      $similarity = (count($intersection)/ (max(count($wordsA),count($wordsB))) * 100);
      $similarity =  number_format($similarity, 2, '.', '');
      $variation = 100-$similarity;
      return $variation;
}