<p>A minimal perfect hash function (MPHF) maps a set&#xa0;<i>S</i> of <i>n</i> keys to the first <i>n</i> integers without collisions. There is a lower bound of <InlineEquation ID="IEq1"> <InlineMediaObject> <ImageObject Color="BlackWhite" FileRef="453_2025_1321_Article_IEq1.gif" Format="GIF" Height="19" Rendition="HTML" Resolution="72" Type="Linedraw" Width="196" /> </InlineMediaObject> <EquationSource Format="TEX">\(n\log _2e-\mathcal {O}(\log n) \approx 1.44n\)</EquationSource> <EquationSource Format="MATHML"><math> <mrow> <mi>n</mi> <msub> <mo>log</mo> <mn>2</mn> </msub> <mi>e</mi> <mo>-</mo> <mi mathvariant="script">O</mi> <mrow> <mo stretchy="false">(</mo> <mo>log</mo> <mi>n</mi> <mo stretchy="false">)</mo> </mrow> <mo>≈</mo> <mn>1.44</mn> <mi>n</mi> </mrow> </math></EquationSource> </InlineEquation> bits needed to represent an MPHF. This can be reached by a <i>brute-force</i> algorithm that tries <InlineEquation ID="IEq2"> <InlineMediaObject> <ImageObject Color="BlackWhite" FileRef="453_2025_1321_Article_IEq2.gif" Format="GIF" Height="14" Rendition="HTML" Resolution="72" Type="Linedraw" Width="18" /> </InlineMediaObject> <EquationSource Format="TEX">\(e^n\)</EquationSource> <EquationSource Format="MATHML"><math> <msup> <mi>e</mi> <mi>n</mi> </msup> </math></EquationSource> </InlineEquation> hash function seeds in expectation and stores the first seed that leads to an MPHF. The most space-efficient previous algorithms for constructing MPHFs all use such a brute-force approach as a basic building block. In this paper, we introduce ShockHash – <b>S</b>mall, <b>h</b>eavily <b>o</b>verloaded cu<b>ck</b>oo <b>hash</b> tables for minimal perfect hashing. ShockHash uses two hash functions <InlineEquation ID="IEq3"> <InlineMediaObject> <ImageObject Color="BlackWhite" FileRef="453_2025_1321_Article_IEq3.gif" Format="GIF" Height="16" Rendition="HTML" Resolution="72" Type="Linedraw" Width="17" /> </InlineMediaObject> <EquationSource Format="TEX">\(h_0\)</EquationSource> <EquationSource Format="MATHML"><math> <msub> <mi>h</mi> <mn>0</mn> </msub> </math></EquationSource> </InlineEquation> and <InlineEquation ID="IEq4"> <InlineMediaObject> <ImageObject Color="BlackWhite" FileRef="453_2025_1321_Article_IEq4.gif" Format="GIF" Height="16" Rendition="HTML" Resolution="72" Type="Linedraw" Width="17" /> </InlineMediaObject> <EquationSource Format="TEX">\(h_1\)</EquationSource> <EquationSource Format="MATHML"><math> <msub> <mi>h</mi> <mn>1</mn> </msub> </math></EquationSource> </InlineEquation>, hoping for the existence of a function <InlineEquation ID="IEq5"> <InlineMediaObject> <ImageObject Color="BlackWhite" FileRef="453_2025_1321_Article_IEq5.gif" Format="GIF" Height="19" Rendition="HTML" Resolution="72" Type="Linedraw" Width="109" /> </InlineMediaObject> <EquationSource Format="TEX">\(f : S \rightarrow \{0,1\}\)</EquationSource> <EquationSource Format="MATHML"><math> <mrow> <mi>f</mi> <mo>:</mo> <mi>S</mi> <mo stretchy="false">→</mo> <mo stretchy="false">{</mo> <mn>0</mn> <mo>,</mo> <mn>1</mn> <mo stretchy="false">}</mo> </mrow> </math></EquationSource> </InlineEquation> such that <InlineEquation ID="IEq6"> <InlineMediaObject> <ImageObject Color="BlackWhite" FileRef="453_2025_1321_Article_IEq6.gif" Format="GIF" Height="21" Rendition="HTML" Resolution="72" Type="Linedraw" Width="93" /> </InlineMediaObject> <EquationSource Format="TEX">\(x \mapsto h_{f(x)}(x)\)</EquationSource> <EquationSource Format="MATHML"><math> <mrow> <mi>x</mi> <mo>↦</mo> <msub> <mi>h</mi> <mrow> <mi>f</mi> <mo stretchy="false">(</mo> <mi>x</mi> <mo stretchy="false">)</mo> </mrow> </msub> <mrow> <mo stretchy="false">(</mo> <mi>x</mi> <mo stretchy="false">)</mo> </mrow> </mrow> </math></EquationSource> </InlineEquation> is an MPHF on <i>S</i>. It then uses a 1-bit retrieval data structure to store <i>f</i> using <InlineEquation ID="IEq7"> <InlineMediaObject> <ImageObject Color="BlackWhite" FileRef="453_2025_1321_Article_IEq7.gif" Format="GIF" Height="19" Rendition="HTML" Resolution="72" Type="Linedraw" Width="62" /> </InlineMediaObject> <EquationSource Format="TEX">\(n + o(n)\)</EquationSource> <EquationSource Format="MATHML"><math> <mrow> <mi>n</mi> <mo>+</mo> <mi>o</mi> <mo stretchy="false">(</mo> <mi>n</mi> <mo stretchy="false">)</mo> </mrow> </math></EquationSource> </InlineEquation>&#xa0;bits. In graph terminology, ShockHash generates <i>n</i>-edge random graphs until stumbling on a <i>pseudoforest</i> – where each component contains as many edges as nodes. Using cuckoo hashing, ShockHash then derives an MPHF from the pseudoforest in linear time. We show that ShockHash needs to try only about <InlineEquation ID="IEq8"> <InlineMediaObject> <ImageObject Color="BlackWhite" FileRef="453_2025_1321_Article_IEq8.gif" Format="GIF" Height="19" Rendition="HTML" Resolution="72" Type="Linedraw" Width="113" /> </InlineMediaObject> <EquationSource Format="TEX">\((e/2)^n \approx 1.359^n\)</EquationSource> <EquationSource Format="MATHML"><math> <mrow> <msup> <mrow> <mo stretchy="false">(</mo> <mi>e</mi> <mo stretchy="false">/</mo> <mn>2</mn> <mo stretchy="false">)</mo> </mrow> <mi>n</mi> </msup> <mo>≈</mo> <mn>1</mn> <mo>.</mo> <msup> <mn>359</mn> <mi>n</mi> </msup> </mrow> </math></EquationSource> </InlineEquation> seeds in expectation. This reduces the space for storing the seed by roughly <i>n</i> bits (maintaining the asymptotically optimal space consumption) and speeds up construction by almost a factor of <InlineEquation ID="IEq9"> <InlineMediaObject> <ImageObject Color="BlackWhite" FileRef="453_2025_1321_Article_IEq9.gif" Format="GIF" Height="14" Rendition="HTML" Resolution="72" Type="Linedraw" Width="18" /> </InlineMediaObject> <EquationSource Format="TEX">\(2^n\)</EquationSource> <EquationSource Format="MATHML"><math> <msup> <mn>2</mn> <mi>n</mi> </msup> </math></EquationSource> </InlineEquation> compared to brute-force. <i>Bipartite</i> ShockHash reduces the expected construction time again to about <InlineEquation ID="IEq10"> <InlineMediaObject> <ImageObject Color="BlackWhite" FileRef="453_2025_1321_Article_IEq10.gif" Format="GIF" Height="14" Rendition="HTML" Resolution="72" Type="Linedraw" Width="46" /> </InlineMediaObject> <EquationSource Format="TEX">\(1.166^n\)</EquationSource> <EquationSource Format="MATHML"><math> <mrow> <mn>1</mn> <mo>.</mo> <msup> <mn>166</mn> <mi>n</mi> </msup> </mrow> </math></EquationSource> </InlineEquation> by maintaining a pool of candidate hash functions and checking all possible pairs. Using ShockHash as a building block within the RecSplit framework we obtain ShockHash-RS, which can be constructed up to 3 orders of magnitude faster than competing approaches. ShockHash-RS can build an MPHF for 10 million keys with 1.489 bits per key in about half an hour. When instead using ShockHash after an efficient <i>k</i>-perfect hash function, it achieves space usage similar to the best competitors, while being significantly faster to construct and query.</p>

错误:搜索内容不能为空,请输入英文关键词
错误:关键词超出字数限制,请精简
高级检索

ShockHash: Near Optimal-Space Minimal Perfect Hashing Beyond Brute-Force

  • Hans-Peter Lehmann,
  • Peter Sanders,
  • Stefan Walzer

摘要

A minimal perfect hash function (MPHF) maps a set S of n keys to the first n integers without collisions. There is a lower bound of \(n\log _2e-\mathcal {O}(\log n) \approx 1.44n\) n log 2 e - O ( log n ) 1.44 n bits needed to represent an MPHF. This can be reached by a brute-force algorithm that tries \(e^n\) e n hash function seeds in expectation and stores the first seed that leads to an MPHF. The most space-efficient previous algorithms for constructing MPHFs all use such a brute-force approach as a basic building block. In this paper, we introduce ShockHash – Small, heavily overloaded cuckoo hash tables for minimal perfect hashing. ShockHash uses two hash functions \(h_0\) h 0 and \(h_1\) h 1 , hoping for the existence of a function \(f : S \rightarrow \{0,1\}\) f : S { 0 , 1 } such that \(x \mapsto h_{f(x)}(x)\) x h f ( x ) ( x ) is an MPHF on S. It then uses a 1-bit retrieval data structure to store f using \(n + o(n)\) n + o ( n )  bits. In graph terminology, ShockHash generates n-edge random graphs until stumbling on a pseudoforest – where each component contains as many edges as nodes. Using cuckoo hashing, ShockHash then derives an MPHF from the pseudoforest in linear time. We show that ShockHash needs to try only about \((e/2)^n \approx 1.359^n\) ( e / 2 ) n 1 . 359 n seeds in expectation. This reduces the space for storing the seed by roughly n bits (maintaining the asymptotically optimal space consumption) and speeds up construction by almost a factor of \(2^n\) 2 n compared to brute-force. Bipartite ShockHash reduces the expected construction time again to about \(1.166^n\) 1 . 166 n by maintaining a pool of candidate hash functions and checking all possible pairs. Using ShockHash as a building block within the RecSplit framework we obtain ShockHash-RS, which can be constructed up to 3 orders of magnitude faster than competing approaches. ShockHash-RS can build an MPHF for 10 million keys with 1.489 bits per key in about half an hour. When instead using ShockHash after an efficient k-perfect hash function, it achieves space usage similar to the best competitors, while being significantly faster to construct and query.