怎么卡飞哈希

哈希

我们定义一个把字符串映射到整数的函数 f,这个 f 称为是 Hash 函数,我们希望这个函数 f 可以方便地帮我们判断两个字符串是否相等,这就是哈希。

一般来说,哈希值都是使用 hashi=(basehashi1+si)%mod 这个转移方程得到的。

在这个转移方程中,s 为字符串,base 被称为底数,而 mod 被称为模数。

生日悖论

如果一个班级有 23 个人, 那么其中有两个人生日相同的概率超过 50%。因为这与自己的直觉相不符,所以被称为生日悖论。

其实出现这样问题的原因是并没有将“两个人的生日相同”和“有人和自己的生日相同”很好的区分开。

定义两人生日重复的情况叫同生缘。

假设一年有 N 天,那么不发生同生缘的概率可以写作:

1P=i=1n1(1iN)

nN 时,因为 (11N)n1nN,所以

1Pi=1n1(11N)i=(11N)n(n1)2

P=1(11N)n(n1)2

N=365 时,函数图像可点击此链接查看。

可以观察到,在 n=23P 已经接近了 50%

卡大质数哈希

假设模数为 109+7,构造一个长度为 105 的字符串。

将这个数据带入上方函数,得到成功让字符串哈希冲突的概率为 P=0.993261715159

所以直接使用随机构造的方式,在一般情况下就可以将其 hack。

#include<bits/stdc++.h>
using namespace std;
int main(){
    printf("100000 20\n");
    for(int i = 1;i <= 100000;i++){
        putchar(rand() % 26 + 'a');
    }
    return 0;
}

自然溢出

自然溢出,即 hash 数组使用 unsigned long long,也就是对于 264 取模。不光其值域不难出现哈希冲突,而且代码长度与常数都会大大减小,得到了不少的同学的青睐。

N=264,n=105 带入上面的函数后,我们发现出现哈希冲突的可能性 P 无限接近与 0,所以使用生日攻击成功的可能性极小。

底数为偶数

可以构造全部为 a 的子串和第一个为 b 其余均为 a 的两个长度相等且长苏大于 64 的两个不一样的字符串。

因为底数的 64 次方以上模 264 都是 0,所以即是两个字符串不同,他们的哈希值也都会一样。

底数为奇数

设一些串 ssi 表示第 i 个串,si 的哈希值为 hash(si)

定义 f(s) 为字符串 s 内全部的 a 都变为 b,所有的 b 都变成 a

定义 si+sj 的意思为将 sj 添加到 si 的末尾形成的新的字符串。

构造方法为:s1=asi=si1+f(si1),所以 |si|=2i1

所以:

hash(si)=hash(si1)base|si1|+hash(f(si1))=hash(si1)base2i2+hash(f(si1))

hash(f(si1))=hash(f(si2))base2i2+hash(si1)

hash(si)hash(f(si1))=(hash(si1)hash(f(si2)))base2i2(hash(si1)hash(f(si2)))

hash(si)hash(f(si1))=(hash(si1)hash(f(si2)))(base2i21)

因为希望产生哈希冲突,即 264hash(si)hash(f(si))

gi 表示 hash(si)hash(f(si)),那么 g 满足一下性质:

gi=gi1(basei21)

因为每一个 base2i11 都是偶数,所以是的 g 到达第 64 项就可以 hack 了。

因为 base2i11=(base2i21)(base2i2+1) 且为一个偶数乘一个偶数, 而左边的可以继续递归下去, 所以到第 12 位其实就可以 hack 了。

#include <iostream>
#include <cstring>
using namespace std;
char s[10000];
int main(){
	cout<<(1<<12)+65<<' '<<(1<<11)<<'\n';
	int now=1;
	s[1]='a';
	for (int i=1;i<=12;i++){
		for (int j=1;j<=now;j++) s[now+j]=s[j]=='a'?'b':'a';
		now<<=1;
	}
	for (int i=1;i<=now;i++) printf("%c",s[i]);
	for (int i=1;i<=65;i++) putchar('a');
	return 0;
}

参考文章 博客园

posted @   未抑郁的刘大狗  阅读(116)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示