PAT A1022 搜索与格式化输入

PAT A 1022 Digital Library
A 1022

这题主要涉及两点

  1. 数据的组织及搜索
  2. 格式化读入数据

PAT A1022 搜索与格式化输入_第1张图片


数据组织及搜索

这题数据量大(<=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
而结果是PAT A1022 搜索与格式化输入_第2张图片
一输入回车便将两个值都读入了,此时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个方法

用C语言的scanf

//scanf读取1:□
scanf("%d: ",&query_index);
//然后整行读入剩下字符
getline(cin,line);

用cin.ignore跳过

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

AC代码

#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补齐

你可能感兴趣的:(PAT)