倒排索引

概念

它是一种用于搜索文档的方法。一般场景用于给出一个关键字,返回这个关键字相应的文章的集合。

案列

假设我们有如下几篇文档

  • D1 = “谷歌地图之父跳槽Facebook”   
  • D2 = “谷歌地图之父加盟Facebook”   
  • D3 =“谷歌地图创始人拉斯离开谷歌加盟Facebook”   
  • D4 = “谷歌地图创始人跳槽Facebook与Wave项目取消有关”
  • D5 = “谷歌地图创始人拉斯加盟社交网站Facebook”

对每篇文档都进行分词以后,可以这些文档中包含的关键词有:{谷歌,地图,之父,跳槽,Facebook,加盟,创始人,拉斯,离开,与,Wave,项目,取消,有关,社交,网站}
首先,去掉“与”这样的没有实际表意作用的停用词。 然后,对每一个词建立一个链表,表中的每个元素都是包含该词的某篇文档的标识。 于是,得到如下的倒排链集合:

  • 谷歌—{D1,D2,D3,D4,D5}
  • 地图—{D1,D2,D3,D4,D5}
  • Facebook—{D1,D2,D3,D4,D5}
  • 创始人—{D3,D4,D5}
  • 加盟—{D2,D3,D5}
  • 拉斯—{D3,D5}
  • 之父—{D1,D2}
  • 跳槽—{D1,D2}
  • 离开—{D3}
  • 取消—{D4}
  • 项目—{D4}
  • 有关—{D4}
  • 社交—{D5}
  • 网站—{D5}
实现思想

我们主要使用unordered_map / map 来实现,所以查询文档的关键字集合时间复杂度在O(1)和O(lg^2N)。
我们可以使用 大概这样的结构 map < string,List < int > > inverted index;
这里写图片描述
通过map 快速查找对应关键词,然后对应关键词上有相关联的文章集合

代码实现
#include <iostream>
#include <map>
#include <list>
#include <vector>
#include <string>
#include <set>

using namespace std;


class InvIndex : public map<string, list<int>>
{
public:
    vector<vector<string>> docs; //文档正排表

public:
    //向索引中加入一个文档
    void add(vector<string>& doc)
    {
        //在正排表里记录该文档
        docs.push_back(doc);
        int curDocID = docs.size();  //现在代码:使得文档编号从1开始 原始代码:int curDocID = docs.size()-1;

        //遍历doc里所有的term
        for (int w = 0; w < doc.size(); w++)
        {
            map<string,list<int>>::iterator it;
            it = this->find(doc[w]);

            //如果该term的倒排链不存在,新建倒排链
            if (it == this->end())
            {
                (*this)[doc[w]] ;
                it = this->find(doc[w]);
            }

            //在倒排链末尾插入新的文档
            it->second.push_back(curDocID);
        }
    }

    //在索引中进行一次查询
    void retrieve(vector<string>& query, set<int>& docIDs)
    {
        int termNum = query.size();

        //合并所有term的倒排链
        docIDs.clear();
        for (int t = 0; t < termNum; t++)
        {
            map<string,list<int>>::iterator it;
            //该term倒排链不存在则跳过
            if ((it = this->find(query[t])) != this->end())
                docIDs.insert(it->second.begin(),it->second.end());
        }

    }
};


int main()
{

    string D1_tmp[] = {"谷歌","地图","之父","跳槽","Facebook"};
    int D1_tmp_size = sizeof(D1_tmp)/sizeof(string);
    vector<string> D1(D1_tmp,D1_tmp+D1_tmp_size);

    string D2_tmp[] = {"谷歌","地图","之父","加盟","Facebook"};
    int D2_tmp_size = sizeof(D2_tmp)/sizeof(string);
    vector<string> D2(D2_tmp,D2_tmp+D2_tmp_size);

    string D3_tmp[] = {"谷歌","地图","创始人","拉斯","离开","谷歌","加盟","Facebook"};
    int D3_tmp_size = sizeof(D3_tmp)/sizeof(string);
    vector<string> D3(D3_tmp,D3_tmp+D3_tmp_size);

    string D4_tmp[] = {"谷歌","地图","创始人","跳槽","Facebook","与","Wave","项目","取消","有关"};
    int D4_tmp_size = sizeof(D4_tmp)/sizeof(string);
    vector<string> D4(D4_tmp,D4_tmp+D4_tmp_size);

    string D5_tmp[] = {"谷歌","地图","创始人","拉斯","加盟","社交","网站","Facebook"};
    int D5_tmp_size = sizeof(D5_tmp)/sizeof(string);
    vector<string> D5(D5_tmp,D5_tmp+D5_tmp_size);

    InvIndex * inverted_index = new InvIndex<string>;
    inverted_index->add(D1);
    inverted_index->add(D2);
    inverted_index->add(D3);
    inverted_index->add(D4);
    inverted_index->add(D5);


    string str_query[] = {"谷歌","地图","之父","跳槽","Facebook","创始人","加盟","拉斯","离开","与","Wave","项目","取消","有关","社交","网站"};



    for(int i = 0; i < sizeof(str_query)/sizeof(string); i++)
    {
        vector<string> query;
        query.push_back(str_query[i]);

        cout << str_query[i] << " ";

        set<int> docSet;

        inverted_index->retrieve(query,docSet);

        set<int>::iterator it;
        for (it = docSet.begin(); it != docSet.end(); it++)
        {
            cout << "D" << *it << " ";
        }
        cout << endl;

    }

    return 0;
}

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值