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; }