PAT A 1022 Digital Library
A 1022
这题主要涉及两点
这题数据量大(<=10000条书本信息),搜索次数多(<=1000次搜索),如果用一个struct组织数据
struct Book
{
int book_id,published_year;
string title, author, publisher;
vector<string> key_words;
};
那么每次搜索时要遍历整个表比对关键字,如果按key_word查询,还会有大量的重复查找操作(一共只有<=1000条不同的key_word,如果平均每个struct Book有5个key_word的,则最多有10000*5个key_word的,有大量的重复),这样查找是妥妥的运行超时。
注:关键字 ≠ key_word
一本书除了book_id外还有5个关键字查询条件:title\author\publisher\key_words\published_year
按照这些条件建立印射
比如
输入
1111111
The Testing Book
Yue Chen
test code debug sort keywords
ZUCS Print
2011
那么建立5个map< string,set< int>>
string是关键字类型,set储存所有符合关键字的book_id
用一个array来组织
array<map<string,set<int>>,5> Lib;
//Lib[0] ⇒ 按title储存
//Lib[1] ⇒ 按author储存
//Lib[2] ⇒ 按key_words储存
//Lib[3] ⇒ 按publisher储存
//Lib[4] ⇒ 按published_year储存
解决的数据组织的问题,下一个问题是将给出的数据按格式读入
题目将所有的key_words一行给出,我们要逐个读入,并且事先不知道key_words的确切个数
解决方法是使用stringstream
cin读入按空格分割
getline读入一整行,按回车分割
string line,word;
stringstream ss;
//读入一整行
getline(cin,line);
//将字符串绑定到流
ss.str(line);
//流中所有的数据读完后,返回false
while(ss>>word)
{
//......
}
注意点
getline以回车作分割的标志,将输入流中回车之前的值读入
//Example
int a;
string line;
//先读入一个整型数
cin>>a;
getline(cin,line);
cout << a << endl
<< line << endl;
我们试图输入
123
abc def
让a读入123,line读入abc def
而结果是
一输入回车便将两个值都读入了,此时line读入空字符串
原因就是上面讲的getline以回车为信号,输入流为345,345先被a提取,然后流中为空,此时遇到了回车,则将空字符串提取给line
在不同行读入数据之间加一个getchar
cin>>a;
getchar();
getline(cin,line);
cout << a << endl
<< line << endl;
查询操作时,给出的数据格式是:
1: The Testing Book
其中 1 是我们想要读入查询序号,后面的 The Testing Book 是需要整行读入的关键字
对于这个问题有2个方法
//scanf读取1:□
scanf("%d: ",&query_index);
//然后整行读入剩下字符
getline(cin,line);
basic_istream& ignore(
streamsize _Count = 1,
int_type _Delim = traits_type::eof( )
);
cin.ignore有两个参数,第一个 _Count是最大跳过的字符数,第二个 _Delim是跳过的最后一个字符
//Example
//最大跳过200个字符,或者以‘ ’为它最后一个跳过的字符
getline(cin.ignore(200,' '),line);
//输入 2: abc def
//line为abc def 没有前置空格
因此对于题中的格式我们可以这样读入
int query_id;
string query_word;
cin>>query_id;
//注意此时query_id和query_word在同一行,没有多余的回车
getline(cin.ignore(200,' '),query_word);
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main()
{
array<map<string, set<int>>, 5> Lib;
int N,M;
int book_id;
string line,word;
int query_index;
cin >> N;
while (N--)
{
cin >> book_id;
getchar();
for (size_t i = 0; i < 5; i++)
{
getline(cin, line);
if (i == 2)
{
istringstream iss(line);
while (iss>>word)
{
Lib[i][word].insert(book_id);
}
}
else
{
Lib[i][line].insert(book_id);
}
}
}
cin >> M;
getchar();
while (M--)
{
scanf("%d: ", &query_index);
getline(cin, line);
cout << query_index << ": " << line << endl;
auto res = Lib[query_index - 1].find(line);
if (res != Lib[query_index-1].end())
{
for (auto id : res->second)
{
printf("%07d\n",id);
}
}
else
{
cout << "Not Found" << endl;
}
}
system("pause");
return 0;
}
这题还有一个容易忽略导致AC不了的点是,book_id是7位数字,如果是用int储存的,对于0000123这种有前置0的,最后输出会变成 123 ,
因此要输出7位,不足用前置0补齐