news 2026/8/29 2:32:20

信奥赛C++提高组csp-s之哈表表

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
信奥赛C++提高组csp-s之哈表表

信奥赛C++提高组csp-s之哈表表

一、哈希表基本概念

1.1 什么是哈希表

哈希表(Hash Table)是一种高效的数据结构,它通过键值对存储数据,能够在平均O(1)时间内完成插入、删除和查找操作。

1.2 核心思想

键(key)通过哈希函数转换成数组下标,然后将值存储在该下标对应的位置。

索引=哈希函数()%数组大小
1.3 哈希表的组成部分
  1. 键(Key):用于查找的唯一标识
  2. 值(Value):存储的数据
  3. 哈希函数(Hash Function):将键映射为索引
  4. 哈希表(数组):存储数据的容器
  5. 冲突解决机制:处理不同键映射到同一位置的情况

二、哈希函数的构造

2.1 除余法(最常用)
// 基本除余法公式hash_value=key%table_size;// 注意:table_size最好取质数,可以减少冲突
2.2 其他常见哈希函数
// 1. 直接定址法:h(key) = a*key + b// 2. 平方取中法:先平方,取中间几位// 3. 折叠法:将key分成几部分,相加// 4. 乘法散列法:h(key) = floor(m * (key*A mod 1))
2.3 字符串哈希
// 常用字符串哈希函数intstring_hash(conststring&s){inthash_val=0;for(charc:s){hash_val=(hash_val*base+c)%mod;}returnhash_val;}

三、解决冲突的方法

3.1 链地址法(拉链法)

将哈希到同一位置的所有元素存储在链表中。

优点

  • 实现简单
  • 可存储任意数量元素
3.2 开放定址法

当发生冲突时,寻找下一个空闲位置。

探测方法

  1. 线性探测(hash(key) + i) % size
  2. 平方探测(hash(key) + i²) % size
  3. 双重哈希(hash1(key) + i*hash2(key)) % size
3.3 再哈希法

使用多个不同的哈希函数,当第一个哈希函数发生冲突时,使用第二个。

四、案例研究(字符串哈希)

题目描述

如题,给定N NN个字符串(第i ii个字符串长度为M i M_iMi,字符串内包含数字、大小写字母,大小写敏感),请求出N NN个字符串中共有多少个不同的字符串。

输入格式

第一行包含一个整数N NN,为字符串的个数。

接下来N NN行每行包含一个字符串,为所提供的字符串。

输出格式

输出包含一行,包含一个整数,为不同的字符串个数。

输入输出样例 1
输入 1
5 abc aaaa abc abcc 12345
输出 1
4
说明/提示
数据范围

对于30 % 30\%30%的数据:N ≤ 10 N\leq 10N10M i ≈ 6 M_i≈6Mi6M max ⁡ ≤ 15 M_{\max}\leq 15Mmax15

对于70 % 70\%70%的数据:N ≤ 1000 N\leq 1000N1000M i ≈ 100 M_i≈100Mi100M max ⁡ ≤ 150 M_{\max}\leq 150Mmax150

对于100 % 100\%100%的数据:N ≤ 10000 N\leq 10000N10000M i ≈ 1000 M_i≈1000Mi1000M max ⁡ ≤ 1500 M_{\max}\leq 1500Mmax1500

样例说明

样例中第一个字符串a b c \tt{abc}abc和第三个字符串a b c \tt{abc}abc是一样的,所以所提供字符串的集合为{ a a a a , a b c , a b c c , 12345 } \{\tt{aaaa},\tt{abc},\tt{abcc},\tt{12345}\}{aaaa,abc,abcc,12345},故共计4 44个不同的字符串。

思路分析
1.哈希函数设计
  • 采用经典的多项式哈希方法(Rolling Hash)
  • 公式:h = h * base + char
  • 使用无符号长整型的自然溢出实现模运算,简化代码
  • 基数P选择质数131,减少哈希冲突
2.算法流程
  1. 读入n个字符串
  2. 对每个字符串计算哈希值
  3. 将所有哈希值排序
  4. 遍历排序后的哈希值,统计不同的个数
代码实现(方法1)
#include<bits/stdc++.h>usingnamespacestd;// 使用无符号长整型存储哈希值,利用其自动溢出特性实现模运算typedefunsignedlonglongULL;constintN=10010;// 最大字符串数量constULL P=131;// 哈希基数(质数),通常选择131或13331ULL a[N];// 存储每个字符串的哈希值// 字符串哈希函数:将字符串转换为64位无符号整数ULLgetHash(string s){ULL h=0;// 初始化哈希值为0for(charc:s){// 遍历字符串中的每个字符h=h*P+c;// 计算哈希值:h = h * base + char}returnh;// 返回哈希值}intn;// 字符串个数intmain(){cin>>n;// 读入字符串个数// 处理每个字符串for(inti=1;i<=n;i++){string s;cin>>s;// 读入一个字符串a[i]=getHash(s);// 计算并存储其哈希值}// 对哈希值数组排序,便于统计不同值sort(a+1,a+n+1);// 统计不同哈希值数量(即不同字符串数量)intcnt=1;// 至少有1个不同的字符串for(inti=2;i<=n;i++){if(a[i]!=a[i-1]){// 如果当前哈希值与上一个不同cnt++;// 计数增加}}cout<<cnt;// 输出结果return0;}
复杂度分析(方法1)
1.时间复杂度
  • 计算哈希值:O(ΣMᵢ),其中Mᵢ是每个字符串的长度
  • 排序:O(N log N),N≤10000
  • 总体复杂度可接受
2.空间复杂度
  • 存储哈希值:O(N)
  • 存储临时字符串:O(最大字符串长度)
注意事项(方法1)
哈希冲突问题

当前代码存在哈希冲突的可能性,即不同的字符串可能产生相同的哈希值。虽然概率很低,但对于严格要求的场景,可以采取以下改进措施:

  1. 使用双哈希:用两个不同的基数和模数计算哈希值
  2. 使用更大的模数:如取模一个大质数
  3. 实际比较字符串:当哈希值相同时,比较原始字符串
数据范围考虑
  • N最大10000,每个字符串最长1500
  • 哈希值使用ULL(64位),溢出概率低
  • 排序10000个ULL值在时间和空间上都可行
代码实现(方法2)
#include<bits/stdc++.h>// 包含所有标准库头文件(竞赛常用,但不推荐生产环境使用)usingnamespacestd;// 使用标准命名空间intn;// 字符串个数unordered_set<string>st;// 使用无序集合存储字符串,自动去重intmain(){cin>>n;// 读入字符串个数for(inti=1;i<=n;i++){string s;// 临时变量存储当前字符串cin>>s;// 读入一个字符串st.insert(s);// 将字符串插入集合(自动去重)}cout<<st.size();// 输出集合大小,即不同字符串的数量return0;}
方法2思路分析:
1.算法思想
  • 直接利用C++ STL的unordered_set容器,自动完成字符串去重
  • 通过统计集合大小得到不同字符串的数量
2.数据结构选择
  • unordered_set
    • 底层使用哈希表实现
    • 插入和查找的平均时间复杂度为O(1)
    • 自动去重,相同字符串只存储一次
    • 不保证元素的存储顺序
3.时间复杂度分析
  • 插入N个字符串:O(N),每个字符串的插入平均O(1)
  • 总时间复杂度:O(N),其中N为字符串个数
  • 实际运行时间受字符串长度影响(字符串比较和哈希计算需要时间)
4.空间复杂度分析
  • 存储所有不同的字符串:O(M),其中M为所有不同字符串的总长度
  • 哈希表的额外开销:O(K),其中K为不同字符串的数量
5.优缺点分析

优点:

  1. 代码简洁:只需要10行左右的核心代码
  2. 逻辑清晰:直接使用STL,不需要手动实现哈希函数
  3. 运行高效unordered_set的哈希表实现非常高效
  4. 正确性保证:STL经过了充分测试,能正确处理哈希冲突

缺点:

  1. 内存占用较大:存储了整个字符串内容,而不仅仅是哈希值
  2. 理论上可能超时:虽然对于本题数据范围足够,但在极端情况下,如果字符串非常长,哈希计算可能成为瓶颈

五、STL中的哈希表实现

5.1 unordered_map(无序映射)

C++11引入的基于哈希表的关联容器。

#include<bits/stdc++.h>usingnamespacestd;voidtest(){// 创建unordered_mapunordered_map<int,string>m;// 插入元素(三种方式)m[1001]="张三";// 方式1m.insert({1002,"李四"});// 方式2m.insert(make_pair(1003,"王五"));// 方式3// 遍历(无序)cout<<"遍历unordered_map:"<<endl;for(constauto&pair:m){cout<<"学号: "<<pair.first<<", 姓名: "<<pair.second<<endl;}// 查找元素autoit=m.find(1002);if(it!=m.end()){cout<<"找到学号1002: "<<it->second<<endl;}// 统计元素数量cout<<"元素数量: "<<m.size()<<endl;// 检查键是否存在if(m.count(1004)>0){cout<<"学号1004存在"<<endl;}else{cout<<"学号1004不存在"<<endl;}// 删除元素m.erase(1001);cout<<"删除1001后数量: "<<m.size()<<endl;// 清空哈希表m.clear();cout<<"清空后数量: "<<m.size()<<endl;}
5.2 unordered_set(无序集合)

只存储键的哈希表。

#include<bits/stdc++.h>usingnamespacestd;voidtest(){// 创建unordered_setunordered_set<int>s;// 插入元素s.insert(10);s.insert(20);s.insert(30);s.insert(20);// 重复元素,不会被插入// 遍历cout<<"集合元素: ";for(intnum:s){cout<<num<<" ";}cout<<endl;// 查找元素if(s.find(20)!=s.end()){cout<<"元素20在集合中"<<endl;}// 统计元素数量cout<<"集合大小: "<<s.size()<<endl;}

六、信奥赛备考建议

  1. 掌握基本概念:理解哈希函数、冲突解决等基本概念
  2. 熟练使用STL:unordered_map和unordered_set是信奥赛中的利器
  3. 理解时间复杂度
    • 平均情况:插入、删除、查找都是O(1)
    • 最坏情况:所有元素冲突,退化为O(n)
  4. 选择合适的哈希函数:根据题目特点设计合适的哈希函数
  5. 注意边界条件:处理哈希表满、空等特殊情况
  6. 实践练习:多做题,如统计问题、查找问题、去重问题等

七、常见问题与解答

Q: 为什么哈希表查找快?
A: 哈希表通过哈希函数直接计算出存储位置,避免了线性搜索。

Q: 哈希冲突是什么?如何处理?
A: 不同键映射到同一位置就是哈希冲突。常用处理方法有链地址法和开放定址法。

Q: STL中map和unordered_map有什么区别?
A: map基于红黑树实现,有序,操作复杂度O(log n);unordered_map基于哈希表,无序,平均复杂度O(1)。

Q: 如何选择哈希表容量?
A: 选择质数作为容量可以减少冲突,同时考虑负载因子(元素数量/容量),通常保持在0.7以下。

更多系列知识,请查看专栏:《信奥赛C++提高组csp-s知识详解及案例实践》:
https://blog.csdn.net/weixin_66461496/category_13113932.html

各种学习资料,助力大家一站式学习和提升!!!

#include<bits/stdc++.h>usingnamespacestd;intmain(){cout<<"########## 一站式掌握信奥赛知识! ##########";cout<<"############# 冲刺信奥赛拿奖! #############";cout<<"###### 课程购买后永久学习,不受限制! ######";return0;}
  • 一、CSP信奥赛C++通关学习视频课:
    • C++语法基础
    • C++语法进阶
    • C++算法
    • C++数据结构
    • CSP信奥赛数学
    • CSP信奥赛STL
  • 二、CSP信奥赛C++竞赛拿奖视频课:
    • 信奥赛csp-j初赛高频考点解析
    • CSP信奥赛C++复赛集训课(12大高频考点专题集训)
  • 三、csp高频考点知识详解及案例实践:
    • CSP信奥赛C++之动态规划
    • CSP信奥赛C++之标准模板库STL
    • 信奥赛C++提高组csp-s知识详解及案例实践
  • 四、考级、竞赛刷题题单及题解:
    • GESP C++考级真题题解
    • CSP信奥赛C++初赛及复赛高频考点真题解析
    • CSP信奥赛C++一等奖通关刷题题单及题解

详细内容:

1、csp/信奥赛C++,完整信奥赛系列课程(永久学习):

https://edu.csdn.net/lecturer/7901 点击跳转


2、CSP信奥赛C++竞赛拿奖视频课:

https://edu.csdn.net/course/detail/40437 点击跳转

3、csp信奥赛高频考点知识详解及案例实践:

CSP信奥赛C++动态规划:
https://blog.csdn.net/weixin_66461496/category_13096895.html点击跳转

CSP信奥赛C++标准模板库STL:
https://blog.csdn.net/weixin_66461496/category_13108077.html 点击跳转

信奥赛C++提高组csp-s知识详解及案例实践:
https://blog.csdn.net/weixin_66461496/category_13113932.html

4、csp信奥赛冲刺一等奖有效刷题题解:

CSP信奥赛C++初赛及复赛高频考点真题解析(持续更新):https://blog.csdn.net/weixin_66461496/category_12808781.html 点击跳转

CSP信奥赛C++一等奖通关刷题题单及题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12673810.html 点击跳转

5、GESP C++考级真题题解:

GESP(C++ 一级+二级+三级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12858102.html 点击跳转

GESP(C++ 四级+五级+六级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12869848.html 点击跳转

· 文末祝福 ·

#include<bits/stdc++.h>usingnamespacestd;intmain(){cout<<"跟着王老师一起学习信奥赛C++";cout<<" 成就更好的自己! ";cout<<" csp信奥赛一等奖属于你! ";return0;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/25 18:29:53

从零搭建Qwen2.5-7B推理服务|vLLM加速全步骤解析

从零搭建Qwen2.5-7B推理服务&#xff5c;vLLM加速全步骤解析 随着大语言模型能力的持续进化&#xff0c;Qwen2.5系列在知识广度、编程与数学推理、长文本生成及多语言支持等方面实现了显著跃升。其中&#xff0c;Qwen2.5-7B-Instruct作为70亿参数级别的指令微调模型&#xff0…

作者头像 李华
网站建设 2026/8/25 8:55:16

Rembg模型解释:显著性检测原理剖析

Rembg模型解释&#xff1a;显著性检测原理剖析 1. 智能万能抠图 - Rembg 在图像处理与内容创作领域&#xff0c;自动去背景&#xff08;Image Matting / Background Removal&#xff09;是一项高频且关键的需求。无论是电商商品图精修、社交媒体头像设计&#xff0c;还是AI生…

作者头像 李华
网站建设 2026/8/22 0:04:14

2026年入门网络安全工程师要学习哪些内容

大家都知道网络安全行业很火&#xff0c;这个行业因为国家政策趋势正在大力发展&#xff0c;大有可为!但很多人对网络安全工程师还是不了解&#xff0c;不知道网络安全工程师需要学什么?知了堂小编总结出以下要点。 网络安全工程师是一个概称&#xff0c;学习的东西很多&…

作者头像 李华
网站建设 2026/8/19 14:23:41

性能最佳实践

最佳实践&#xff08;Best Practices&#xff09;是指在特定领域或特定任务中&#xff0c;被广泛认可并被认为是最有效、最高效、最安全的方法或做法。它们是基于经验、实践和研究得出的&#xff0c;旨在提供一种可靠的指导&#xff0c;以帮助人们在特定情境下取得良好的结果。…

作者头像 李华
网站建设 2026/8/26 15:56:14

Rembg高精度抠图保姆级教程:电商商品去背景实战

Rembg高精度抠图保姆级教程&#xff1a;电商商品去背景实战 1. 引言&#xff1a;智能万能抠图 - Rembg 在电商、广告设计和内容创作领域&#xff0c;高质量的图像去背景处理是提升视觉表现力的关键环节。传统手动抠图耗时耗力&#xff0c;而自动化工具有时难以应对复杂边缘&a…

作者头像 李华
网站建设 2026/8/21 14:54:14

H5交互设计:从策划到上线的实用方法论与避坑要点

做了7年H5设计&#xff0c;见过太多“为炫酷而炫酷”的翻车案例——比如加了5秒开场动画&#xff0c;用户还没看到核心信息就划走&#xff1b;比如把报名按钮藏在第三屏&#xff0c;转化率低到1%&#xff1b;再比如安卓机上字体乱码&#xff0c;iOS上动画卡顿。其实H5的核心从来…

作者头像 李华