首页 > 其他分享 >字符串 & 哈希

字符串 & 哈希

时间:2024-07-22 18:09:05浏览次数:7  
标签:map 映射 int CF 哈希 字符串

由于笔者不常使用哈希,且整理不够全面,本文只做启发。

哈希

寻找一个映射函数\(f\)把一个集合映射到一个有限集合,使得不同元素映射的值不同,相同元素的值相同。

我们希望这个函数能让我们快速判断两个字符串是否相同。

构造

字符串的哈希一般构造如下:

template<unsigned bas = 131, unsigned mod = 998244353>
struct HASH {
    char s[MAXN]; int n;
    ull f[MAXN], pw[MAXN];
    void init(int _n) {
        n = _n;
        pw[0] = 1;
        for (int i = 1; i <= n; ++i)
            f[i] = (1ull * f[i - 1] * bas + s[i]) % mod,
            pw[i] = 1ull * pw[i - 1] * bas % mod;
    }
    ull sub(int l, int r) {
        return (f[r] - f[l - 1] * pw[r - l + 1] % mod + mod) % mod;
    }
};

字符串的左边系数更大,因为这么构造能够轻易的去除字符串的任意子串的哈希值。

哈希碰撞

我们认为,映射函数\(f\)设计的足够好的时候,每个位置都是等概率被映射到的。那么哈希碰撞的概率就是\(\frac{n \times (n-1) /2}{mod}\)。即所有不同子串都映射到mod值域里。不推荐使用自然溢出的原因就是,\(f\)的映射不够优秀,导致某些位置容易被映射到。

不知道哪里听到的一句话

现在的出题人都默认卡单哈希

所以一般用双哈希来避免哈希碰撞。

unordered_map

unordered_map是通过哈希表来实现的。理论上复杂度应该是\(O(1)\)的,但不知道为什么,跑的经常没有map快。而且基数确定,经常被出题人卡。但是可以通过如下代码自定义哈希映射函数:

struct hashfunc {
    template<typename T, typename U>
    size_t operator() (const pair<T, U> &i) const {
        return hash<T>()(i.first) ^ hash<U>()(i.second);
    }
};
unordered_map< pair<int, int>, int , hashfunc > mp;

应用

哈希广泛应用于各种“乱搞”。

  • 字符串匹配,判断\(S1\)是否是\(S2\)的子串
  • 判断\(S\)字符串是否回文
    求出\(S\)和\(S^R\)的哈希,判断是否相等。(R代表翻转)
  • 寻找\(S\)和\(T\)的lcp(最长公共前缀)
    二分长度,哈希判断是否相等。

等等

其他的哈希映射方式 xor-hash

考虑这么一个问题:快速判断两个集合是否相等?(集合是无需的)

考虑一种满足交换律的运算作为哈希映射方式。就可以解决无需问题。
如:异或。

首先,我们把元素随机映射到mod值域内,降低哈希碰撞概率。然后异或起来就是哈希值。

for (int i = 1; i <= n; ++i)
    f[i] = rnd() % mod;
for (int i = 1; i <= n; ++i)
    pre[i] = pre[i - 1] ^ f[a[i]];

应用

  • 判断一个序列内的元素是否出现偶数(\(k\)的倍数)次
    异或起来为0,否则为非0。
    \(k\)的倍数:手写一个$ k $进制xor,但是会多个log常数

例题:

线段树 & 哈希

考虑以下问题:字符串\(S\)长度为\(|T|\)的子串是否和字符串\(T\)每个元素相对大小位置一样。
如:\(S = [1, 2, 5, 4, 6]\),\(T = [2, 1, 5]\),那么\(S[3,5]\)和\(T\)的相对大小位置一样。

哈希有很好的性质,只要知道这个字符的相对位置,就能算出这个字符对哈希的贡献。考虑开权值线段树。在\(pushup\)的时候重新构造字符串哈希,最后判断相等即可。

例题:

标签:map,映射,int,CF,哈希,字符串
From: https://www.cnblogs.com/Qing17/p/18316614

相关文章

  • 保存 Cisco 设备配置的 2 个字符串之间的区别
    我有2个变量,config1和config2保存Cisco设备在2个不同时间点的运行配置。运行配置示例:version12.3noservicepadservicetimestampsdebugdatetimemsecservicetimestampslogdatetimemsecnoservicepassword-encryption!hostnameretail!boot-star......
  • Day6 哈希表part1
    目录哈希表任务242.有效的字母异位词思路349.两个数组的交集思路202.快乐数思路1.两数之和思路总结哈希表什么时候用哈希表呢?快速判断元素是否在集合中,或者元素去重(集合),或者统计重复元素的数量(字典)。任务242.有效的字母异位词给定两个字符串s和t,编写一个函数来判断t......
  • c++中字符串之string和char
    c++string初始化的几种方式相对于C#来说,c++中string的初始化方式真的非常多,比如以下都可以用来初始化string:usingnamespacestd;intmain(){ stringstr1="test01";//直接赋值 stringstr2(5,'c');//结果:str2='ccccc',以length为长度的ch的拷贝(即length个ch) ......
  • Redis底层数据结构-简单动态字符串SDS
    简单动态字符串(simpledynamicstring,SDS)。Redis没有直接使用C语言传统的字符串,而是自己构建了一种简单动态字符串(SDS)的抽象类型。C字符串只会作为字符串字面量(stringliteral)用在一些无须对字符串值进行修改的地方。实现sds.h/sdshdrstruct__attribute__((__packed__)......
  • 字符串和数字过滤器
    什么是过滤器?实质上就是一个转换函数。变量可以通过“过滤器”进行修改,过滤器可以理解为是jinja2里面的内置函数和字符串处理函数。常用的过滤器有: 1、字符串的过滤器<body>{#当变量未定义时,显示默认字符串,可以缩写为d#}<p>{{name|default('Noname')}}</p>{#单词首......
  • leetcode位运算(1684. 统计一致字符串的数目)
    前言经过前期的基础训练以及部分实战练习,粗略掌握了各种题型的解题思路。后续开始专项练习。描述实现原理与步骤1.本题重点掌握相应字符bit位的编码规则2.bitArray和tempBitArray或之后还等于bitArray,说明bitArray包含tempBitArray代码实现classSolution{publ......
  • 常见的Python编程题目及其代码(十二)-- 56. 检查字符串是否只包含数字57. 找到列表中出
    目录56.检查字符串是否只包含数字57.找到列表中出现次数最多的元素58.计算字符串中的元音数59.计算字符串中的辅音数60.找到字符串中的最长单词 56.检查字符串是否只包含数字s="12345"print(s.isdigit())57.找到列表中出现次数最多的元素fromcollection......
  • 字符串的创建辨析
    字符串的创建辨析Strings="1"*使用引号创建字符串会在常量池中寻找有则直接返回没有则创建Strings=newString("1");*使用new创建如果常量池没有"1"则在常量池中创建"1"再在堆中创建String并返回地址给引用*使用s.intern()如果常量池中没有与字符串相同的字符串(判......
  • Leetcoede编程基础0到1——459.重复的子字符串 & 283.移动零 &1822.数组元素积的符号
    459.重复的子字符串给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。示例1:输入:s="abab"输出:true解释:可由子串"ab"重复两次构成。示例2:输入:s="aba"输出:false示例3:输入:s="abcabcabcabc"输出:true解释:可由子......
  • 【Python将字符串连接在一起】
    当然,Python是一个功能丰富且灵活的语言,有许多技巧和最佳实践可以帮助你更有效地编写代码。以下是一些常见的Python技巧:列表推导式(ListComprehensions):这是一种简洁的构建列表的方法。它比使用循环更加清晰和Pythonic。[x*2forxinrange(5)]#输出:[0,2,4,6,......