news 2026/4/23 17:44:25

【例3-2】单词查找树(信息学奥赛一本通- P1337)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【例3-2】单词查找树(信息学奥赛一本通- P1337)

【题目描述】

在进行文法分析的时候,通常需要检测一个单词是否在我们的单词列表里。为了提高查找和定位的速度,通常都画出与单词列表所对应的单词查找树,其特点如下:

1.根结点不包含字母,除根结点外每一个结点都仅包含一个大写英文字母;

2.从根结点到某一结点,路径上经过的字母依次连起来所构成的字母序列,称为该结点对应的单词。单词列表中的每个单词,都是该单词查找树某个结点所对应的单词;

3.在满足上述条件下,该单词查找树的结点数最少。

4.例如图3-2左边的单词列表就对应于右边的单词查找树。注意,对一个确定的单词列表,请统计对应的单词查找树的结点数(包含根结点)。

【输入】

为一个单词列表,每一行仅包含一个单词和一个换行/回车符。每个单词仅由大写的英文字母组成,长度不超过63个字母 。文件总长度不超过32K,至少有一行数据。

【输出】

仅包含一个整数,该整数为单词列表对应的单词查找树的结点数。

【输入样例】

A AN ASP AS ASC ASCII BAS BASIC

【输出样例】

13

1. 关于那个“文件总长度 32K”

题目给的限制很有意思:

  1. 单词长度不超过 63。

  2. 文件总长度不超过 32K。

第一眼看到 63,下意识觉得“这题很小”,随手开了个 tre[2000]。结果仔细一算不对劲:

32K 是多少?

在C++里,一个char就是 1 字节。

32K=32*1024=32768字节。

这意味着最坏情况下(比如所有单词都长得不一样),这棵树得存 3 万多个字符。

如果要建树,数组至少得开到 40000+ 才稳。

要是按 2000 开,读到第 2001 个字符的时候程序直接就炸了(越界)。

教训:以后看到 32K、64M 这种单位,第一反应必须是换算成字节数。

2. 为什么用 vector 存 Trie?

通常 Trie 树节点是这样写的:

struct node { char data; node* next[26]; // 或者 int next[26] };

这样写查找快,但如果节点很多且分叉少,空间浪费严重。

改用vector邻接表写法:

struct node { char data; vector<int> son; // 只存存在的儿子下标 } tre[50000]; // 数组一定要开够!

虽然查找时要遍历son数组(多一个 for 循环),但省内存,而且代码写起来其实就是个 DFS,很符合直觉。

3. 最终代码

逻辑很简单:

  1. 拿着字符串当前字符a[k2]去当前节点k1son列表里找。

  2. 找到了 -> 递归下一层。

  3. 找不到 ->push_back一个新节点,把ind传进去继续递归。

#include <bits/stdc++.h> #include <vector> using namespace std; struct node{ char data;//记录该结点是哪个字母 vector<int> son;//存放该结点的儿子在树中的下标 }tre[50000];//要开大一点,题目中说文件总长度不超过32K,32k=三万多字节,所以开五万 int cnt;//节点个数 string a; //让tre[1]存放root int len; int ind=1;//现在已经添加了ind个节点,初始为1,因为根节点为root,不包含任何字母 void dfs(int k1,int k2){//现在遍历到树第k1个节点,字符串遍历到第k2个位置 if(k2==len) return; bool flag=0; for(int i=0;i<tre[k1].son.size();i++){//遍历该节点所有孩子,如果和字符串该位置的字母有对应,就去找下一个对应 if(tre[tre[k1].son[i]].data==a[k2]){//如果对应上了,就进入下一轮遍历 dfs(tre[k1].son[i],k2+1); flag=1; break;//对应上了就不需要再找了,退出此轮循环 } } if(flag==0){//目前没有能匹配上的 tre[++ind].data=a[k2];//把a[k2]创建一个新节点,然后储存起来 tre[k1].son.push_back(ind);//把a[k2]节点存进父节点的孩子里,就是拼接上去 dfs(ind,k2+1); } } int main(){ while(cin>>a){ len=a.size();//字符串长度 //建树 //长度不超过63个字母 即每次读进来的单词最多63个字符 dfs深度最多63层 dfs(1,0);//从树的第1个节点开始遍历,从a字符串的a[0]开始遍历 } cout<<ind; }

4. 总结

  • 空间换算char是 1 字节,题目给多少 K 就乘多少 1024,数组宁大勿小。

  • Vector 写法:用vector代替定长数组写 Trie 是完全可行的,特别适合不想算next[26]或者字符集不只是 26 个字母的情况。

  • 下标坑vector存的是下标,取数据时记得套两层tre[tre[k1].son[i]],这里最容易晕。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 11:35:12

芯片架构深度解析:从晶体管到计算系统的艺术

1 概述&#xff1a;数字时代的基石芯片架构是现代计算设备的核心灵魂&#xff0c;它决定了计算系统的性能、能效和适用场景。从智能手机到超级计算机&#xff0c;从自动驾驶汽车到物联网设备&#xff0c;芯片架构的设计理念直接影响着数字世界的运行效率。芯片架构本质上是晶体…

作者头像 李华
网站建设 2026/4/23 9:52:58

12、应用安装与发布全解析

应用安装与发布全解析 1. 引言 在瘦客户端计算中,应用程序的安装和发布是两个至关重要的概念。安装应用程序需要选择与环境兼容的应用,将其安装在服务器上,进行测试,并在必要时自定义环境以确保应用按预期运行。发布应用程序则改变了我们传统的连接特定服务器并运行其上安…

作者头像 李华
网站建设 2026/4/23 16:13:08

3、Windows 2000 远程访问与路由服务全解析

Windows 2000 远程访问与路由服务全解析 1. 远程访问概述 远程访问服务器为需要访问公司服务器上数据和应用程序的远程用户提供服务。早期,大型计算机的远程终端是连接和使用网络应用程序的主要方式,之后用户对连接网络中的个人电脑产生需求,远程控制应运而生。为满足大量…

作者头像 李华
网站建设 2026/4/23 11:35:42

Kotaemon FlashAttention应用:加快注意力计算

Kotaemon FlashAttention应用&#xff1a;加快注意力计算 在构建现代智能问答系统时&#xff0c;一个看似不起眼却极具破坏力的问题时常浮现&#xff1a;用户问完问题后&#xff0c;系统“卡住了”。尤其是当对话历史越积越长、检索到的知识片段越来越丰富时&#xff0c;GPU显存…

作者头像 李华
网站建设 2026/4/23 11:35:42

修心与修Bug:当程序员遇见“世上本无事,庸人自扰之”

作为一名程序员&#xff0c;我们的生活似乎由无数具体的“事”构成&#xff1a;永远改不完的需求、凌晨两点的紧急告警、技术选型的无限纠结、同辈压力的持续炙烤……在这个复杂系统里&#xff0c;“无事”简直是天方夜谭。然而&#xff0c;那句源自古老东方智慧的“世上本无事…

作者头像 李华
网站建设 2026/4/23 9:59:26

军用装备视觉识别与分类_yolov10n-PST模型详解

1. YOLO系列模型创新点大盘点 在目标检测领域&#xff0c;YOLO系列模型一直是大家关注的焦点。从最初的YOLOv1到现在的YOLOv13&#xff0c;每个版本的迭代都带来了不少创新点。今天我们就来详细盘点一下这些模型中的核心技术&#xff0c;看看它们是如何一步步提升检测性能的。…

作者头像 李华