Универсальное хеширование
Чтобы вычислить вероятность коллизий между S
строками длины L
с W
битами на символ и хэшем длиной H
бит при оптимальном универсальный хэш (1), вы можете рассчитать вероятность коллизии на основе хэш-таблицы размера (количество сегментов) 'N`.
Прежде всего, мы можем предположить идеальную реализацию хеш-таблицы (2), которая идеально разбивает H
битов хэша на доступные сегменты N
(3). Это означает, что H
становится бессмысленным, за исключением ограничения для N
. W
и 'L' - это просто основа для верхней границы S
. Для более простой математики предположим, что строки длиной ‹ L
просто дополняются до L специальным нулевым символом. Если бы нас это интересовало, нас бы интересовал худший случай, это 54^L
(26*2+'_'+ null), очевидно, это смехотворное число, фактическое количество записей более полезно, чем набор символов и длина поэтому мы просто будем работать так, как если бы S
была переменной сама по себе.
Осталось попытаться поместить S
предметов в N
ведер. Затем это становится очень известной проблемой, парадоксом дня рождения.
Решая это для различных вероятностей и количества ковшей поучительно, но предполагая, что мы имеем 1 миллиард сегментов (то есть около 4 ГБ памяти в 32-битной системе), тогда нам потребуется всего 37 КБ записей, прежде чем мы достигнем 50% вероятности того, что они будут хотя бы одним столкновением. Учитывая, что попытка избежать любых коллизий в хеш-таблице становится просто абсурдной.
Все это не означает, что мы не должны заботиться о поведении наших хеш-функций. Очевидно, что эти цифры предполагают идеальные реализации, они являются верхней границей того, насколько хорошо мы можем добиться. Плохая хеш-функция может привести к гораздо более серьезным коллизиям в некоторых областях, растратить часть возможного «пространства», никогда или редко используя его, все это может привести к тому, что хэши будут менее оптимальными, и даже ухудшится до производительности, которая выглядит как список, но с гораздо хуже постоянными факторами.
Реализация .NET framework хеш-функции строки не очень хороша (в том смысле, что она могла бы быть лучше), но, вероятно, приемлема для подавляющего большинства пользователей и достаточно эффективна для вычислений.
Альтернативный подход: идеальное хэширование
Если вы хотите генерировать так называемые идеальные хэши, вам потребуется полное знание входных значений. заранее однако так не часто полезно. По аналогии с приведенной выше математикой мы можем показать, что даже идеальное хеширование имеет свои пределы:
Напомним ограничение в 54 ^ L
строк длины L
. Однако у нас есть только H
бит (предположим, 32), что составляет около 4 миллиардов различных чисел. Итак, если у вас может быть действительно любая строка и любое их количество, вы должны удовлетворить:
54 ^ L <= 2 ^ 32
И решить это:
log2 (54 ^ L) <= 32
L * log2 54 <= 32
L <= 32 / log2 54 <= 5.56
Поскольку длина строки явно не может быть дробной, у вас остается максимальная длина всего 5. Действительно очень короткая.
Если вы знаете, что у вас когда-либо будет набор строк размером намного меньше 4 миллиардов, то идеальное хеширование позволит вам обрабатывать любое значение L
, но ограничение набора значений на практике может быть очень сложным, и вы должны знать их все на практике. продвигаться или снижаться до того, что составляет базу данных строк -> хэш, и добавлять к ней по мере обнаружения новых строк.
Для этого упражнения универсальный хэш является оптимальным, так как мы хотим уменьшить вероятность любой коллизии, то есть для любого входа вероятность того, что он имеет выход x из набора возможностей R, равна 1/R.
Обратите внимание, что выполнить оптимальную работу по хэшированию (и внутренней группировке) довольно сложно, но вы должны ожидать, что встроенные типы будут разумными, если не всегда идеальными.
В этом примере я избегал вопроса о закрытой и открытой адресации. Это имеет некоторое влияние на вовлеченные вероятности, но незначительно.
person
Community
schedule
09.04.2009