Cuckoo Hashing
Time limit1sMemory limit128 MB
Given each word's two hash slots, decide whether inserting all words in order avoids an infinite cuckoo eviction chain.
Problem
One of the most fundamental data-structure problems is the dictionary problem: given a set of words, you want to quickly decide whether any query string belongs to . Hashing is a classic solution. You design a fast, deterministic hash function that maps every string into the integer range , allocate an empty table of size , and for each word set . To answer a query you compute and check whether .
The catch is collisions: two different words may hash to the same slot (recall the birthday paradox — in a class of 24 pupils there is already more than a 50% chance that two share a birthday). On average you can only store about words before a collision occurs, which wastes a lot of space.
Cuckoo hashing is a stronger variant that uses two hash functions and , so each word has two candidate slots. To answer a query you compute both and and report that if or .
The name comes from how the table is built. Start with an empty table and insert the words one by one. To insert a word :
- If is free, set .
- Otherwise, if is free, set .
- Otherwise both slots are occupied. Like a cuckoo pushing other birds' eggs out of the nest, evict the word currently in , set , and reinsert into its alternative slot. If that slot is also occupied, evict its word and relocate it in the same way, and so on.
This relocation chain may never terminate. If it loops forever, the table has to be rebuilt with different hash functions. Fortunately, with high probability this does not happen as long as contains at most words.
Given, for every word, the two slots it hashes to, decide whether all words can be inserted in the given order without falling into an infinite relocation loop.
(Cuckoo hashing was proposed by R. Pagh and F. F. Rödler in 2001.)
Input
The first line contains a single integer (), the number of test cases.
Each test case starts with a line containing two integers and (), where is the number of words in the dictionary and is the size of the hash table. Each of the next lines describes one word (in insertion order) by two integers and (), its two hash values. The two values may be equal.
Output
For each test case, print a single line: successful hashing if all words can be inserted in the given order, or rehash necessary if it is impossible.