怎么把字符串变成数组_字符串哈希:从零开始的十分钟包会教程

9ec044cec04b2016e18dd799334886bf.png

大家吼啊!这是我下定决心写专栏以来的第二篇文章,请大家多多资瓷!!同样我们先以上次的话起头吧!

恭喜你找到了这篇博客!虽然这个标题看起来非常像是nc营销号的标题但是!请相信我一次这是真的!如果不行请随时取关!(等等你好像还没关注我那不如现在先关注看完再取关吧哈哈

好了不跟你多BB,想象你现在有一堆数,你要把他们装进一堆桶里,相同的数放在一起,你会怎么做呢?

9e2076b788502f199996785866370255.png

哦这太简单了!只要在每个桶上面标上这个数,然后把数丢进相应的桶不就完了?

149cfca9ce8ca84838d98cfcfa436d0b.png

(咦?怎么有个桶看起来就很蠢的样子)

那我们在程序上怎么实现这个桶呢?

啊答主你是没学过数组还是怎么的!直接开一个a[1000],假设来了一个数x,就让a[x]自加1不就行了!

好啊!但你这有个小问题。要是来一个9999怎么办?开a[10000]?

那要是来99999呢?987654321呢?或者更直接,来个字符串呢?

711b03f3d5909d93ef1c6ed1d6d1cec4.png

难道要开字符串为下标的数组?这怎么可能呢。

字符串到整数的唯一映射——字符串哈希

让我们想想问题出在哪。下标必须是一个不太大的正整数,也就是说,我们要将一个字符串变成一个不太大的正整数

首先我们将每个字符看做等于他的ASCII码的整数,这样字符串就变成了一个数串,且每个数不超过127(只有字母和数字的话ASCII是不超过127的)。

26aa7cc359f26209e80514a7bf7b96c8.png

f2865667b699ed7b4b05e75a98575985.png

现在我们就来突发奇想啦!怎么才能用一个数表示这个数组呢?

从前有这样一种东西,它的每一位都不超过127,也就是说不到128……

啊!这不就是一个128进制的数吗!

从左到右,分别代表了这个128进制数的从高位到低位……

然而我们现在知道的是这个数的每一位,要得到这个数是很简单的。

比如[100,55]这个数有两位,

那么这个数的值就是100×128+55=12855

有三位的话,如[127,100,55],

那就是127×(128^2)+100×128+55=2093623

那么我们只需要提前处理出128的若干次方,然后分别与这个数的每一位相乘,就能得到这个数了!

完美!

等等,128的5次方不就超出int范围了吗?

超就超!

要知道我们实际上要建立的是一个单射关系,即只要能通过一个字符串推出一个唯一确定的数,我们的目的就达到了。

我其实是求出了这个128进制数的值的,只是最后将它映射到了int范围里的数。

这时聪明的读者说:你这样损失了信息,万一两个128进制数本来不同,这么一搞给你搞成相同的了那不完犊子了?

考虑到这个数已经很大了,将它mod一下int范围,其实已经相当于int范围内的随机数了,只是这个数是由字符串唯一确定的。

既然是随机数,那不同的字符串映射到相同数的概率,就跟在0~2147483647里随机取两个数,它们相等的概率一样了。

在实际中,我们可以认为这个概率就是0。

完美!!!

当然,现在这个数的范围是0~2147483647。如果想要继续缩小范围,那么可以再mod一个随便什么数,原理同上。

当然你mod的数也不能太小。具体如果你取N,那么平均情况下在计算到第1.17*√N个字符串时有50%的概率会重复(证明可搜“生日攻击”)。所以建议在不超过限度的情况下尽量取大。

int 

喜欢的话就支持一下啦,想笔者出什么文章或者有什么建议也可以在评论区说☆

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值