HOJ 2551 Zoogle 题解
题目大意:
有标签式的数据描述,每组数据由<case> </case>标签隔开。
每组数据中有若干个<page></page>隔开的页面描述,每个page中<url> </url>之间是这个page的url地址,<text></text>之间是正文,保证正文每个单词用空格隔开,没有标点,每个正文最多512个词,每个page中还有<link></link>标记的链接描述,<link></link>之间可能出现别的页面的url,在别的页面中外部链接中出现的次数为页面的权值。
请求由<query></query>标记,最多有4096个,请求就是可能在page正文中出现的单词,对于每个请求按权值排序列出在正文中出现过这个单词的page的url。
解题思路:
先囧一下,因为在样例输入里面第一个page的正文里面写着“Maybe you can use inverted index to speed up the process”,于是搜索了一下这个inverted index,也就是倒排索引,简单概括就是按照要检索的内容将地址储存下来,具体到这个题目来说把正文当做关键字,储存url,这个用map就非常合适,数据结构是map<string,set<string> >,第二元素是url组成的集合。
想到这里思路就很明显了,对于每个query,直接查找这个单词所在的url,按照权值排序输出就可以了。
STL中用到了map、set。
下面附上代码
#include <iostream>
#include <algorithm>
#include <set>
#include <map>
#include <cstring>
#include <string>
#include <cstdio>
using namespace std;
struct URL
{
char s[2000];
int w;
friend bool operator< (const URL &a, const URL &b)
{
return a.w>b.w || (a.w == b.w && strcmp(a.s,b.s) == -1);
}
}urls[2000],turl;
int main()
{
int T = 0;
char s[2000],url[2000];
while (scanf("%s", s) != EOF)
{
map<string,set<string> > word_index;
map<string,int> url_value;
if (T++) printf("\n");
while(scanf("%s",s) && strcmp(s,"<query>") != 0)
{
scanf("%*s %s %*s %*s",url);
while(scanf("%s",s) && strcmp(s,"</text>") != 0)
word_index[s].insert(url);
scanf("%s",s);
while(scanf("%s",s) && strcmp(s,"</link>") != 0)
url_value[s]++;
scanf("%s",s);
}
printf("<case>\n");
while(scanf("%s",s) && strcmp(s,"</query>") != 0)
{
printf(" <reply query=\"%s\">\n",s);
if(word_index.find(s) == word_index.end())
{
printf(" Sorry, not found...\n </reply>\n");
continue;
}
set<string> st = word_index[s];
int tot = 0;
for (set<string>::iterator it = st.begin(); it != st.end(); it++)
{
turl.w = url_value[*it];
strcpy(turl.s,(*it).c_str());
urls[tot++] = turl;
}
sort(urls,urls+tot);
for (int i = 0; i < tot; i++)
printf(" %s\n",urls[i].s);
printf(" </reply>\n");
}
printf("</case>\n");
scanf("%s",s);
}
return 0;
}

浙公网安备 33010602011771号