Каждый бит является независимым, поэтому на этапе предварительной обработки [*] вы могли бы классифицировать каждую запись 32 (или сколько бы вы ни были int
) раз.Каждая классификация хранит 2 набора: те, которые соответствуют этому биту, когда key
равен 0, и те, которые соответствуют, когда key
равен 1.
То есть, если значение == 1 и маска == 0 при этомбит, то эта классификация вообще не хранит эту запись, поскольку она не соответствует ни одному значению key
(фактически, независимо от используемой схемы, такие записи должны быть удалены на любом этапе предварительной обработки, поэтому нет классификация должна хранить запись, если хотя бы один бит такой).Если оба 0, хранить в обоих наборах.В противном случае сохраните в один из двух наборов.
Затем, учитывая ваш ключ, вы хотите найти быстрое пересечение из 32 наборов.
В зависимости от размера исходного массива, это может бытьчто лучший способ сохранить каждый набор - это гигантский битовый массив, указывающий, находится ли каждая запись в массиве в наборе или нет.Затем найти пересечение можно одним словом за один раз - &
вместе 32 словами, по одному в каждом битовом массиве.Если результат 0, продолжайте.Если результат не равен 0, у вас есть совпадение, и бит, установленный в результате, сообщает вам, какая запись соответствует.Конечно, размер массива по-прежнему линейный, и на самом деле вы выполняете 31 &
операций, чтобы проверить совпадение 32 записей, что примерно равно простому линейному поиску в исходном массиве.Но сравнений и разветвлений меньше, и данные, которые вы просматриваете, более сжаты, так что вы можете получить более высокую производительность.
Или может быть лучший способ сделать пересечение.
Если ключи, как правило, используются повторно, вам следует кэшировать результаты поиска на карте от ключей до записей.Если число возможных ключей достаточно мало (т. Е. Если возможно менее 2 ^ 32 ключей являются возможными входами и / или у вас много свободной памяти), то фаза предварительной обработки может быть просто:
- принимать каждую запись по очереди
- определить, какие возможные ключи ей соответствуют
- добавить ее на карту для этих ключей
[*] Без каких-либопредобработка, очевидно, все, что вы можете сделать, это проверить каждый член массива, пока вы не найдете совпадение или не проверили все.