poj 4093:倒排索引查询

poj 4093:倒排索引查询

题目:
总时间限制: 1000ms 内存限制: 131072kB
描述
现在已经对一些文档求出了倒排索引,对于一些词得出了这些词在哪些文档中出现的列表。

要求对于倒排索引实现一些简单的查询,即查询某些词同时出现,或者有些词出现有些词不出现的文档有哪些。

输入
第一行包含一个数N,1 <= N <= 100,表示倒排索引表的数目。
接下来N行,每行第一个数ci,表示这个词出现在了多少个文档中。接下来跟着ci个数,表示出现在的文档编号,编号不一定有序。1 <= ci <= 1000,文档编号为32位整数。
接下来一行包含一个数M,1 <= M <= 100,表示查询的数目。
接下来M行每行N个数,每个数表示这个词要不要出现,1表示出现,-1表示不出现,0表示无所谓。数据保证每行至少出现一个1。
输出
共M行,每行对应一个查询。输出查询到的文档编号,按照编号升序输出。
如果查不到任何文档,输出"NOT FOUND"。
样例输入
3
3 1 2 3
1 2
1 3
3
1 1 1
1 -1 0
1 -1 -1
样例输出
NOT FOUND
1 3
1

解题方案

我们先考虑两个子问题
1.求出两个有序递增数组的交集,并集,补集
我使用的是归并排序思想,只不过取得元素不同而已
2.求出多个有序递增数组的交集,并集
第一问题是这个问题的子问题,同时使用归并思想去做,如同擂台赛一样,每一个数组如同一个选手去争冠军
好了,子问题解决完毕,我们看看poj题目
1)对每一个索引表排序
2)对每一组查询,找出需要出现的文档号集合 wanted_list 和 不出现的文档号集合 not_wanted_list(这两个问题分别是上述第二个子问题求多个数组的交集,并集问题)
3)求出wanted_list 相对 not_wanted_list的补集即可 

代码c++如下
[cpp] view plaincopy
#include <iostream>  
#include <list>  
#include <algorithm>  
#include <map>  
#include <fstream>  
using namespace std;  
  
class Node  
{  
public:  
    int word_id;  
    int bit;  
};  
  
int compare(const void * a,const void * b)  
{  
    return *(int*)a - *(int *)b;  
}  
  
void print_list(list<int> mylist);  
list<Node> initialize_list(int **search,int row,int N,bool need);  
list<int> sub_data(list<int> wanted_list,list<int> not_wanted_list);  
list<int> find_same_need(list<Node> mylist,int ** data,const int length);  
list<int> find_same_not_need(list<Node> mylist,int ** data,const int length);  
void read_data(int ** &data,int ** & search,int &M,int &N);  
  
int main()  
{  
    int ** data;  
    int ** search;  
    int M,N;  
    list<int> wanted_list;  
    list<int> not_wanted_list;  
    list<Node> wanted_node_list;  
    list<Node> not_wanted_node_list;  
    list<int> result;  
    read_data(data,search,M,N);  
  
    for( int i=0;i<M;i++ )  
    {  
        wanted_node_list = initialize_list(search,i,N,true);  
        not_wanted_node_list = initialize_list(search,i,N,false);  
        wanted_list = find_same_need(wanted_node_list,data,N);  
        not_wanted_list = find_same_not_need(not_wanted_node_list,data,N);  
        result = sub_data(wanted_list,not_wanted_list);  
        print_list(result);  
    }  
    system("pause");  
    return 0;  
  
}  
  
list<int> find_same_need(list<Node> mylist,int ** data,const int length)  
{  
    list<int> result;  
    bool same ;  
    list<Node>::iterator min_node;  
    int min_article_id;  
  
    while( true )  
    {  
        // 1. 检查当前文档号是否是一样的  
        same = true;  
        Node one = mylist.front();  
        for(list<Node>::iterator node = mylist.begin();node != mylist.end(); node++)  
        {  
            if( data[one.word_id][one.bit] != data[node->word_id][node->bit] )  
            {  
                same = false;  
                break;  
            }  
        }  
  
        // 2. 结果如果不相同时,则需要增加最小的  
        if( ! same )  
        {  
            min_article_id = INT_MAX;  
            for(list<Node>::iterator node = mylist.begin();node != mylist.end(); node++)  
            {  
                if( data[node->word_id][node->bit] < min_article_id )  
                {  
                    min_article_id = data[node->word_id][node->bit];  
                    min_node = node;  
                }  
            }  
            min_node->bit ++;  
            // 已经得到所有结果  
            if( min_node->bit > data[min_node->word_id][0] )  
                return result;  
        }  
  
        // 3. 存储一个结果  
        else  
        {  
            result.push_back( mylist.front().bit );  
            for (list<Node>::iterator node = mylist.begin(); node != mylist.end(); node++)  
            {  
                node->bit ++;  
  
                // 已经得到所有结果  
                if( node->bit > data[node->word_id][0] )  
                    return result;  
            }  
        }  
    }  
}  
  
list<int> find_same_not_need(list<Node> mylist,int ** data,const int length)  
{  
    map<int,bool> myamp;  
    list<int> result;  
    for(list<Node>::iterator it = mylist.begin();it != mylist.end() ;it++)  
    {  
        while(it->bit <= data[it->word_id][0])  
        {  
            if( myamp.find(data[it->word_id][it->bit]) == myamp.end() )  
            {  
                myamp.insert(make_pair(data[it->word_id][it->bit],true));  
            }  
            it->bit ++;  
        }  
    }  
    for(map<int,bool>::iterator it = myamp.begin();it!=myamp.end();it++)  
    {  
        result.push_back(it->first);  
    }  
    return result;  
}  
  
  
  
  
list<int> sub_data(list<int> wanted_list,list<int> not_wanted_list)  
{  
    list<int> result;  
    list<int>::iterator wanted_it,not_wanted_it;  
    wanted_it = wanted_list.begin();  
    not_wanted_it = not_wanted_list.begin();  
    while( wanted_it!= wanted_list.end() && not_wanted_it != not_wanted_list.end() )  
    {  
        if( *wanted_it < *not_wanted_it )  
        {  
            result.push_back(*wanted_it) ;  
            wanted_it++;  
        }  
        else if( *wanted_it > *not_wanted_it )  
        {  
            not_wanted_it++;  
        }  
        else  
        {  
            wanted_it++;  
            not_wanted_it++;  
        }  
    }  
    while(wanted_it != wanted_list.end())  
    {  
        result.push_back(*wanted_it);  
        wanted_it++;  
    }  
    return result;  
}  
  
list<Node> initialize_list(int **search,int row,int N,bool need)  
{  
    list<Node> result;  
    Node node;  
    if( need )  
    {  
        for( int i=0;i<N;i++ )  
        {  
            if( search[row][i] == 1 )  
            {  
                node.word_id = i;  
                node.bit = 1;  
                result.push_back( node );  
            }  
        }  
    }  
    else  
    {  
        for( int i=0;i<N;i++ )  
        {  
            if( search[row][i] == -1 )  
            {  
                node.word_id = i;  
                node.bit = 1;  
                result.push_back( node );  
            }  
        }  
    }  
    return result;  
}  
  
void print_list(list<int> mylist)  
{  
    if(mylist.size() > 0)  
    {  
        for(list<int>::iterator it=mylist.begin();it != mylist.end();it++)  
        {  
            cout<<*it<<" ";  
  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值