用于文本相似性的算法/库

时间:2013-05-16 19:46:57

标签: c++ algorithm text

我需要实现算法(或在开源库中找到一个)来评估文本的相似性。我需要一个有效的算法,给定两个任意文档集(相对较少的大块文本),以便在它们之间创建匹配对 - 哪个文档最有可能从哪个文档生成。

我相信我会把它分成两部分 - 定义每对的相似系数 - 然后应用一些赋值问题算法。对于分配算法,我可以找到很多解决方案,我找不到一个好的解决方案来计算相似系数。

请注意,文档事先是未知的 - 文本的计算索引(如果有)也必须快速。

我知道汉明距离,Levenshtein距离一些其他算法的字符串差异。这不是我想要的 - 我正在使用文字而不是字符串。

我不是在寻找短语搜索算法​​以及像Lucene和Xapian这样的库(至少看起来像是这样)。

可能基于tf-idf。

我想问题是,是否有某些东西已经解决了这个问题,或者是否有可能像lucete这样的库来做到这一点。

1 个答案:

答案 0 :(得分:1)

以下是我要做的起点(仅仅因为它简单而快速):

  • 使用共享地图或hash_map将单词映射到数字
  • 对于每个文本,构建相应的字级三元组计数
  • 比较重叠

我们可以假设字典大小是< 1m(或21bit),所以我们可以在int64中编码一个三元组。

void CountTrigrams(const vector<string>& words, 
                   map<string, int> * dict, 
                   map<int64, int> * result) {
  int64 trigram = 0;
  for (int i = 0; i < words.size(); i++) {
    const& word = words[i];
    int id;
    auto di = dict->find(word);
    if (di == dict->end()) {
      id = dict.size();
      dict[word] = id;
    } else {
      id = di->second;
    }
    trigram = ((trigram << 21) | id) & 0x7fffffffffffffff;
    if (i > 2) {
      auto ti = result->find(trigram);
      if (ti == result->end()) {
        result[trigram] = 1;
      } else {
        ti->second++;
      }
    }
  }
}

然后比较每对的结果:

int Compare(const map<int64, int> & t1, const map<int64, int> & t2) {
  int score = 0;
  for (auto i = t1.first(); i != t1.end(); i++) {
    auto j = t2.find(t1->first);
    if (j != t2.end()) {
      score += MAX(i->second, j->second);
    }
  }
  return score;
}

以某种方式将分数标准化可能是有意义的,例如除以三卦总数。