无题
无题
woodfishE题超详解:帮哈基鱼算标签
by woodfish
孩子们,需要承认这题有点小难,难度可能在信息差上,因为可能你们没学到对应知识点,出题人谢罪了orz
给定一段“简化 HTML”字符串,保证:
标签名仅含小写字母、数字;
只有成对出现的普通标签,无自闭合标签;
标签嵌套完全合法,不会出现闭合顺序错误。
要求统计每种标签名的出现次数。
注意:
一次“出现”指一对开始标签
<tag>和结束标签</tag>合起来算一次;结果按标签名字典序(ASCII 序)输出,格式为
标签名=次数。
本题主要考察map和string
接下来一步一步来,把这道题涉及的核心知识点拆成三块讲清楚
map 的键值对特性 & 自动字典序
std::map<Key, T> 是 C++ STL 里的有序关联容器,底层是一颗红黑树。
- 每个节点存
std::pair<const Key, T>,也就是常说的“键值对”。 - 键唯一:同一个
Key只能出现一次,重复插入等价于更新。 - 自动排序:所有键按
<定义的严格弱序排列。
对字符串string来说,<就是字典序(ASCII 序),与题目要求完全一致。
因此只要把“标签名”丢进去当 Key,出现次数当 Value,遍历 map 时就已经天然有序,无需再手写排序。
示例:
1 | map<string,int> mp; |
输出:
1 | apple=5 |
map是C++的一个容器之一,学习下来可以做非常多的题,记得搜索相关视频去掌握
提取标签名字的思路
题目保证:
- 只有成对标签,无自闭合;
- 嵌套合法,不会错位。
于是我们可以只认开始标签 <tag>,忽略结束标签 </tag>。
算法流程:
- 从左到右扫字符串,遇到
'<'就进入“标签模式”。 - 继续往后读,直到遇见
'>',中间那段字符就是标签名。 - 如果标签名第一个字符不是
'/',说明是开始标签,计数器加一。
1 | for (int i = 0; i < s.size(); ++i) { |
- 时间 $O(|S|)$,每个字符最多访问两次。
- 空间 $O(K)$,$K$ 为不同标签种数。
用“类 lambda”语法输出 map
C++11 起提供了范围 for 循环 + 结构化绑定(C++17)的写法,看起来很像 lambda 的简洁风格
Python选手应该对这个很熟悉
1 | for (auto [name, cnt] : mp) // 结构化绑定,name 是键,cnt 是值 |
等价于:
1 | for (map<string,int>::iterator it = mp.begin(); it != mp.end(); ++it) |
但前者更短、更易读,也符合“现代 C++”的审美
综上,可以给出AC代码:
1 | // 万能头,竞赛常用,一把梭包含几乎所有 STL |



