假设我有一个N字符串列表,在编译时已知.
我想生成(在编译时)一个函数,它将每个字符串映射到1到N之间的不同整数.该函数应该花费很少的时间或空间来执行.
例如,假设我的字符串是:
{"apple", "orange", "banana"}
这样的功能可能会返回:
f("apple") -> 2
f("orange") -> 1
f("banana") -> 3
生成此功能的策略是什么?
我想在编译时分析字符串并查找一些我可以修改或添加的常量或其他东西?
编译时生成时间/空间可能非常昂贵(但显然不是那么荒谬).
最佳答案 假设你有不同的字符串,让ai,j成为第i个字符串的第j个字符.在下文中,我将假设它们都具有相同的长度.如果j≥| ai |,通过将ai,j视为空字符,可以很容易地将其转换为任何合理的编程语言.
我建议的想法由两部分组成:
>查找(最多)m – 1个区别字符串的位置,并存储这些位置.
>通过将字符串视为length-m向量并存储完美散列函数的参数来创建完美的散列函数.
显然,一般来说,哈希函数必须检查至少m-1个位置.通过归纳很容易看到这一点.对于2个字符串,必须至少检查1个字符.假设i字符串是真的:i – 必须检查1个位置.通过在每个i字符串的末尾附加0来创建一组新的字符串,并添加一个与其中一个字符串相同的新字符串,除了它在结尾处有一个1.
相反,显而易见的是,最多可以找到足以区分字符串的m-1个位置(对于某些集合,路线的数量可能较低,低至log的字母大小为m的基数).同样,通过归纳很容易看出来.两个不同的字符串在某个位置必须不同.将字符串放在具有m行的矩阵中,必须有一些列不是所有字符都相同.将矩阵划分为两个或多个部分,并将参数递归地应用于具有多于2行的每个部分,显示了这一点.
假设m – 1位置是p1,…,pm – 1.在下面,回想上面的含义为ai,pj为pj≥| ai |:它是空字符.
让我们为随机qj和一些n定义h(ai)=Σj= 1m-1 [qj ai,pj%n].那么h是known to be a universal hash function:对碰撞的概率P(x≠y& wedge; h(x)= h(y))≤1/ n.
给定通用散列函数,有known constructions for creating a perfect hash function from it.也许最简单的是创建一个大小为m2的向量,并连续尝试上面的h,其中n = m2,随机系数,直到没有碰撞.在实现此目标之前所需的尝试次数预计为2,并且需要更多尝试的概率呈指数下降.