#19249. 书童的虚词账本

书童的虚词账本

文言文(Classical Chinese)以言简意赅著称,其中虚词(如“之、乎、者、也”)虽然没有实在的意义,却是构成文章语气和节奏的灵魂。

苏轼在《日喻》中说:“之乎者也,助得甚事?” 但对于信息学来说,统计这些字出现的频率,是考察 哈希表(HashMap) 最经典的场景:我们需要建立一个从“汉字(String)”到“出现次数(Int)”的映射关系。

我为你构思了这道题目,背景设定为一位古代书童整理经书的过程。


[OI 题库] 书童的“虚词账本” (The Scholar's Particle Counter)

题目背景

“学而时习,不亦说?” —— 《论语》

古代的私塾里,老夫子正在讲授经书。书童“小乙”的任务是整理夫子的手稿。夫子最近对文章的韵律非常痴迷,他想知道在这一卷经文中,那些常用的虚词(如“之”、“乎”、“者”、“也”、“矣”、“焉”、“哉”)分别出现了多少次。

经文由一个个汉字组成。由于汉字数量众多,小乙不可能在脑子里记住每一个字的位置。他需要一个神奇的“账本”,每读到一个字,就在账本上对应的名字后面画一道杠(计数)。

题目描述

给定一篇包含 NN 个汉字(或词语)的文言文文章。 再给定 MM 次查询,每次查询给出一个特定的汉字。

请你利用“哈希表”技术,快速回答每一个被查询的汉字在文章中一共出现了多少次。

注意

  1. 输入不考虑标点符号,所有汉字以空格或换行分隔。
  2. 如果没有出现过该字,请输出 0。

输入格式

第一行一个整数 NN,表示文章中汉字的总数。 第二行包含 NN 个字符串,表示文章内容(每个字符串代表一个汉字或词)。 第三行一个整数 MM,表示查询的次数。 接下来 MM 行,每行一个字符串,表示要查询的汉字。

输出格式

MM 行。每行一个整数,表示该汉字在文章中出现的频率。

样例数据

样例 1

10
学 而 时 习 之 不 亦 说 乎 之
3
之
乎
者
2
1
0

样例解析

  • 文章内容:“学 而 时 习 不 亦 说
  • 查询“之”:出现了 2 次。
  • 查询“乎”:出现了 1 次。
  • 查询“者”:文章中未出现,输出 0。

数据范围

  • 1N,M100,0001 \le N, M \le 100,000
  • 输入的汉字(字符串)长度不超过 3 字节(UTF-8编码下的单个汉字)或 10 字节(词组)。
  • 考察点std::unordered_mapstd::map 的基本使用(插入、查找、计数)。

阿西莫夫的解题指南

这道题将语文的 “字义分析” 抽象为了计算机的 “键值对映射(Key-Value Mapping)”

  1. 数据结构选择
    • 如果我们用两个数组,一个存字,一个存次数,每次查询都要遍历整个数组,复杂度是 O(NM)O(N \cdot M),这太慢了。
    • 我们需要一个 O(1)O(1)O(logN)O(\log N) 查询速度的容器。
    • std::map<string, int>(基于红黑树,有序)或 std::unordered_map<string, int>(基于哈希表,无序)是最佳选择。
  2. 核心逻辑
    • 预处理(建表):遍历文章,每读到一个词 s,就执行 counts[s]++。这行代码的含义是:如果在表中找不到 s,则新建并初始化为0再加1;如果找到了,直接加1。
    • 查询:直接输出 counts[query_word]。如果表中不存在该键,STL 的 map 会自动返回 0(默认构造值),非常方便。