稀疏相似度

该博客探讨了一种在大规模文档集中计算稀疏相似度的方法。通过建立哈希表来存储每个单词对应的文档ID,然后计算文档之间的交集与并集比例,确定文档的相似度。算法特别针对相似度接近于0的文档对,有效地减少了计算量。示例展示了输入文档数组和输出的相似文档ID及相似度字符串数组。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

稀疏相似度

两个(具有不同单词的)文档的交集(intersection)中元素的个数除以并集(union)中元素的个数,就是这两个文档的相似度。例如,{1, 5, 3} 和 {1, 7, 2, 3} 的相似度是 0.4,其中,交集的元素有 2 个,并集的元素有 5 个。给定一系列的长篇文档,每个文档元素各不相同,并与一个 ID 相关联。它们的相似度非常“稀疏”,也就是说任选 2 个文档,相似度都很接近 0。请设计一个算法返回每对文档的 ID 及其相似度。只需输出相似度大于 0 的组合。请忽略空文档。为简单起见,可以假定每个文档由一个含有不同整数的数组表示。

输入为一个二维数组 docs,docs[i] 表示 id 为 i 的文档。返回一个数组,其中每个元素是一个字符串,代表每对相似度大于 0 的文档,其格式为 {id1},{id2}: {similarity},其中 id1 为两个文档中较小的 id,similarity 为相似度,精确到小数点后 4 位。以任意顺序返回数组均可。

输入:
[
[14, 15, 100, 9, 3],
[32, 1, 9, 3, 5],
[15, 29, 2, 6, 8, 7],
[7, 10]
]
输出:
[
“0,1: 0.2500”,
“0,2: 0.1000”,
“2,3: 0.1429”
]

思路:哈希表

  1. 先遍历所有文档的所有单词,mp1[word]返回数组,表示包含有单词word的文档id。
  2. 生成mp1需要O(DW)复杂度,D表示文档数量,W表示每个文档的单词数。
  3. 根据mp1,我们就可以判断哪两个文档会相交,只对相交的文档进行相似度计算。即使相似性的计算暴力,因为稀疏。
  4. 知道哪两个文档会相交后,分别排序两个文档内的单词,然后双指针找出两个文档相交元素,进一步计算出这两个文档的相似度。
class Solution {
public:
    vector<string> computeSimilarities(vector<vector<int>>& docs) {
        unordered_map<int, vector<int>> mp1;
        for(int i=0; i<docs.size(); ++i){
            for(auto &word : docs[i]){
                mp1[word].push_back(i);
            }
        }
        unordered_map<int, unordered_map<int, int>> mp2;
        for(auto &item : mp1){
            auto &ids = item.second;
            for(int i=0; i+1<ids.size(); ++i){
                for(int j=i+1; j<ids.size(); ++j){
                    mp2[ids[i]][ids[j]]++;
                }
            }
        }
        
        vector<string> result;
        char temp[256];
        for(auto &item : mp2){
            int id1 = item.first;
            for(auto &item2 : item.second){
                int id2 = item2.first;
                double similary = (double)item2.second / 
                                    (docs[id1].size() + docs[id2].size() - item2.second);
                sprintf(temp, "%d,%d: %0.4lf", id1, id2, similary + 1e-9);
                // cout << temp << endl; // debug
                result.push_back(temp);
            }
        }
        return result;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值