7-3 迷你搜索引擎 (35 分)

实现一种简单的搜索引擎功能,快速满足多达105条关键字查询请求。

输入格式:

输入首先给出正整数 N(≤ 100),为文件总数。随后按以下格式给出每个文件的内容:第一行给出文件的标题,随后给出不超过 100 行的文件正文,最后在一行中只给出一个字符 #,表示文件结束。每行不超过 50 个字符。在 N 个文件内容结束之后,给出查询总数 M(≤105),随后 M 行,每行给出不超过 10 个英文单词,其间以空格分隔,每个单词不超过 10 个英文字母,不区分大小写。

输出格式:

针对每一条查询,首先在一行中输出包含全部该查询单词的文件总数;如果总数为 0,则输出 Not Found。如果有找到符合条件的文件,则按输入的先后顺序输出这些文件,格式为:第1行输出文件标题;随后顺序输出包含查询单词的那些行内容。注意不能把相同的一行重复输出。

输入样例:

4
A00
Gold
silver truck
#
A01
Shipment of gold
damaged
in a fire
#
A02
Delivery
of silver
arrived in
a silver
truck
#
A03
Shipment of gold
arrived in
a truck
#
2
what ever
silver truck

结尾无空行

输出样例:

0
Not Found
2
A00
silver truck
A02
of silver
a silver
truck

结尾无空行

/*2019/10/12 迷你搜索引擎 STL重构*/
#include<string>
#include<cstdio>
#include<vector>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
string fileName[100];
string file[100][100];//第i个文件第j行
const int MAXTABLESIZE = 300009;
struct nodeB
{
    int fileNum;
    set<int> line;
};
struct nodeA
{    
    int lastFile;
    int lastLine;
    string word;
    vector<nodeB> arrayB;
};
/*Hash*/
struct HashTbl
{
    int TableSize;
    nodeA* Cells;
};
typedef struct HashTbl* HashTable;
HashTable CreateTable()
{
    int i;
    HashTable H = new HashTbl;
    H->TableSize = MAXTABLESIZE;
    H->Cells = new nodeA[MAXTABLESIZE];
    for(i=0; i<H->TableSize; i++)
    {
        H->Cells[i].lastFile = -1;
        H->Cells[i].lastLine = -1;
    }
    return H;
}
int Hash(string Key, int P)
{
    int i,len,N;
    unsigned int h = 0;
    for(i=0; i<N; i++)
    {
        h = (h<<5) + (Key[i] - 'a');
    }
    return (h&(32*32*32-1))%P;
}
int Find(HashTable H, string Key)//线形探测法解决冲突
{
    int newPos, curPos,cnt = 0;//cnt表示冲突次数
    newPos = curPos = Hash(Key, H->TableSize);
    while((H->Cells[newPos].lastFile!=-1)&&(H->Cells[newPos].word!=Key))
    {
        cnt++;
        newPos = curPos + cnt;
        if(newPos>=H->TableSize)
            newPos-=H->TableSize;
    }
    return newPos;
}
void Insert(HashTable H, string Key, int file, int line)
{
    nodeB* tmp;
    int pos = Find(H,Key);
    if(H->Cells[pos].lastFile==-1)//表示这个位置为空,那么要先插入单词,再插入文件和行号
    {
        H->Cells[pos].lastFile = file;
        H->Cells[pos].lastLine = line;
        H->Cells[pos].word = Key;//printf("插入了%s\n",Key.c_str());
        tmp = new nodeB;
        tmp->fileNum = file; tmp->line.insert(line);
        H->Cells[pos].arrayB.push_back(*tmp);
    }
    else if(H->Cells[pos].lastFile!=file)
    {
        H->Cells[pos].lastFile = file;
        H->Cells[pos].lastLine = line;
        tmp = new nodeB;
        tmp->fileNum = file; tmp->line.insert(line);
        H->Cells[pos].arrayB.push_back(*tmp);
    }
    else if(H->Cells[pos].lastLine!=line)
    {
        H->Cells[pos].arrayB[H->Cells[pos].arrayB.size()-1].line.insert(line);
    }
}
/*Hash*/
void readFile(HashTable H)
{
    int N,i,j,k;
    string str,buff;
    scanf("%d",&N);getchar();
    char *cstr,*p;
    for(i=0; i<N; i++)//i是文件的编号从0~N-1
    {
        getline(cin,fileName[i]);j = 0;//j代表行号
        while(getline(cin,str), str != "#")
        {
            file[i][j] = str;
            cstr = new char[str.size()+1];
            strcpy(cstr,str.c_str());
            p = strtok(cstr," ");
            while(p!=NULL)
            {
                for(k=0; k<strlen(p); k++)
                {
                    if((p[k]>='A')&&(p[k]<='Z'))
                    {
                        p[k] = p[k] + 32;
                    }
                }
                Insert(H,p,i,j);
                p = strtok(NULL," ");
            }
            j++;
        }
    }
}
void Intersect(vector<nodeB> &v1, vector<nodeB> &v2, vector<nodeB> &v)
{
    vector<nodeB>::iterator it1,it2;
    set<int>::iterator it3,it4;
    it1 = v1.begin(); it2 = v2.begin();
    while(it1!=v1.end()&&it2!=v2.end())
    {
        if(it1->fileNum==it2->fileNum)
        {
            nodeB* tmp = new nodeB;
            tmp->fileNum = it1->fileNum;
            for(it3 = it1->line.begin();it3!=it1->line.end();it3++)
            {
                tmp->line.insert(*it3);
            }
            for(it4 = it2->line.begin();it4!=it2->line.end();it4++)
            {
                tmp->line.insert(*it4);
            }
            v.push_back(*tmp);
            it1++;it2++;
        }
        else if(it1->fileNum<it2->fileNum)
        {
            it1++;
        }
        else
        {
            it2++;
        }
    }
}
void query(HashTable H)
{
    int i,k; string str;
    char* cstr,*p;
    string buff[10];
    getline(cin,str);
    cstr = new char[str.size()+1];
    strcpy(cstr,str.c_str());
    p = strtok(cstr," ");//printf("%s\n", p);
    int cnt = 0;
    while(p!=NULL)
    {
        char* tmp;tmp = p;
        while(*tmp!='\0')
        {
            if(*tmp>='A'&&*tmp<='Z')
            {
                *tmp = *tmp+32;
            }
            tmp++;
        }
        buff[cnt] = p;//cout<<buff[cnt]<<endl;
        cnt++;
        p = strtok(NULL," ");
    }
    vector<nodeB> vi;int pos;vector<nodeB> v;
    for(i=0; i<cnt; i++)
    {
        pos = Find(H,buff[i]);//cout<<"单词是"<<H->Cells[pos].word<<endl;
        if(i==0)
        {
            vi.insert(vi.begin(),H->Cells[pos].arrayB.begin(),H->Cells[pos].arrayB.end());
        }
        else
        {
            Intersect(vi,H->Cells[pos].arrayB,v);
            vi.clear();
            vi.insert(vi.begin(),v.begin(),v.end());
            v.clear();
        }
    }
    cout<<vi.size()<<endl;
    if(vi.size()==0)
    {
        printf("Not Found\n");
        return;
    }
    for(auto it = vi.begin(); it!=vi.end(); it++)
    {
        printf("%s\n",fileName[it->fileNum].c_str());
        for(auto it5=it->line.begin(); it5!=it->line.end(); it5++)
        {
            printf("%s\n",file[it->fileNum][*it5].c_str());
        }
    }
}
int main()
{
    HashTable H = CreateTable();
    readFile(H);
    int M;
    scanf("%d",&M);getchar();
    for(int i=0; i<M;i++)
    {
        query(H);
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值