Fusion tree — различия между версиями
Zernov (обсуждение | вклад) |
Zernov (обсуждение | вклад) |
||
Строка 46: | Строка 46: | ||
Теперь надо найти количество единиц в <tex>L</tex>. Умножим <tex>L</tex> на <tex>\underbrace{0\ldots 01}_{l + 1 bits}\ldots \underbrace{0\ldots 01}_{l+1 bits}</tex>, тогда все единицы сложатся в первом блоке результата, и, чтобы получить количество единиц, сдвинем его вправо на <tex>(k-1)\cdot(l + 1)</tex> бит. В таком случае мы получим некоторое <tex>2^i</tex>, где <tex>i</tex> является реальным <tex>pred(x)</tex>, а <tex>i</tex> мы можем получить с помощью цикла де Брёйна | Теперь надо найти количество единиц в <tex>L</tex>. Умножим <tex>L</tex> на <tex>\underbrace{0\ldots 01}_{l + 1 bits}\ldots \underbrace{0\ldots 01}_{l+1 bits}</tex>, тогда все единицы сложатся в первом блоке результата, и, чтобы получить количество единиц, сдвинем его вправо на <tex>(k-1)\cdot(l + 1)</tex> бит. В таком случае мы получим некоторое <tex>2^i</tex>, где <tex>i</tex> является реальным <tex>pred(x)</tex>, а <tex>i</tex> мы можем получить с помощью цикла де Брёйна | ||
− | == Индекс наиболее старшего бита с помощью цикла де Брёйна == | + | === Индекс наиболее старшего бита с помощью цикла де Брёйна === |
'''Последовательность де Брёйна''' {{---}} последовательность <math>a_1,\;\ldots,\;a_t</math>, элементы которой принадлежат заданному конечному множеству (обычно рассматривают множество <math>\{0,\;1,\;\ldots,\;k-1\}</math>), и все подпоследовательности <math>a_{i+1},\;\ldots,\;a_{i+n}</math> заданной длины <math>n</math> различны. | '''Последовательность де Брёйна''' {{---}} последовательность <math>a_1,\;\ldots,\;a_t</math>, элементы которой принадлежат заданному конечному множеству (обычно рассматривают множество <math>\{0,\;1,\;\ldots,\;k-1\}</math>), и все подпоследовательности <math>a_{i+1},\;\ldots,\;a_{i+n}</math> заданной длины <math>n</math> различны. | ||
− | === Примеры === | + | ==== Примеры ==== |
Примеры циклов де Брёйна для <math>k=2</math> с периодом <tex>2, 4, 8, 16</tex>: | Примеры циклов де Брёйна для <math>k=2</math> с периодом <tex>2, 4, 8, 16</tex>: | ||
Строка 58: | Строка 58: | ||
* <tex>0000100110101111</tex> | * <tex>0000100110101111</tex> | ||
− | === Получение индекса по значению степени двойки === | + | ==== Получение индекса по значению степени двойки ==== |
Возьмем цикл де Брёйна для <tex>n</tex> <tex>(i = 0\ldots n-1)</tex> и запишем его как число <tex>b</tex> (для <tex>8</tex> цикл де Брёна равен <tex>00010111</tex>, а значение <tex>b = 23</tex>). Умножим это число на <tex>2^i</tex>, сдвинем его влево на <tex>i</tex>, а затем обратно вправо на <tex>n-k</tex> (<tex>k</tex> такое, что <tex>n=2^k</tex>). <tex>(b \ll i)\gg(n-k)</tex>), тогда получившееся число {{---}} <tex>i</tex>-ая подстрока длины <tex>k</tex> данного цикла де Брёйна. Эту перестановку опозначим за <tex>p</tex> и тогда применив ее к <tex>(2^i\cdot x) \gg (n-k))</tex> получим <tex>i</tex>: <tex>p</tex> в данном случае такое, что <tex>k</tex> подряд идущих бит равны значению, на сколько мы сдвинули. | Возьмем цикл де Брёйна для <tex>n</tex> <tex>(i = 0\ldots n-1)</tex> и запишем его как число <tex>b</tex> (для <tex>8</tex> цикл де Брёна равен <tex>00010111</tex>, а значение <tex>b = 23</tex>). Умножим это число на <tex>2^i</tex>, сдвинем его влево на <tex>i</tex>, а затем обратно вправо на <tex>n-k</tex> (<tex>k</tex> такое, что <tex>n=2^k</tex>). <tex>(b \ll i)\gg(n-k)</tex>), тогда получившееся число {{---}} <tex>i</tex>-ая подстрока длины <tex>k</tex> данного цикла де Брёйна. Эту перестановку опозначим за <tex>p</tex> и тогда применив ее к <tex>(2^i\cdot x) \gg (n-k))</tex> получим <tex>i</tex>: <tex>p</tex> в данном случае такое, что <tex>k</tex> подряд идущих бит равны значению, на сколько мы сдвинули. |
Версия 11:02, 7 июня 2015
Fusion tree — дерево поиска, позволяющее хранить
-битных чисел, используя памяти, и выполнять операции поиска за время . Это статическая структура данных, которая была впервые предложена в 1990 году М. Фредманом (M. Fredman) и Д. Уиллардом (D. Willard).Структура
Fusion tree — это B-дерево, такое что:
- у всех вершин, кроме листьев, детей,
- время, за которое определяется, в каком поддереве находится вершина, равно .
Такое время работы достигается за счет хранения дополнительной информации в вершинах. Построим цифровой бор из ключей узла дерева. Всего ветвящихся вершин. Биты, соответствующие уровням дерева, в которых происходит ветвление, назовем существенными и обозначим их номера (индексация идет от листьев, которые соответствуют концу числа, т.е. младшему разряду). Количество существенных битов не больше (все ребра на уровне детей ветвящейся вершины — обведены на рисунке — являются существенными битами, и так как ветвящихся вершин , значит, и количество уровней с детьми не больше , поскольку на одном уровне могут быть несколько ветвящихся вершин).
В Fusion tree вместе с ключом
хранится — последовательность битов .Утверждение: |
сохраняет порядок, то есть , если . |
Рассмотрим наибольший общий префикс | и . Тогда следующий бит определяет их порядок и одновременно является существенным битом. Поэтому, если , то и .
Поиск вершины
Пусть
— множество ключей узла, отсортированных по возрастанию, — ключ искомой вершины, — количество бит в . Сначала найдем такой ключ , что . Хотя положение среди не всегда эквивалентно положению среди , зная соседние элементы , мы можем найти и .Поиск следующего и предыдущего по sketch
Утверждение: |
Среди значений и по есть или по значению . |
Рассмотрим | . У него есть существенные биты и некоторый элемент , с которым у наибольший общий префикс (настоящий, а не по ). Биты из , находящиеся в префиксе совпадают, значит и среди должны быть такими же среди , и один из них имеет дальше бит (а другой ) и с ним может быть больше других общих бит в . То есть либо , либо имеют следующий существенный бит такой же, как и у . Поэтому если значение равно , то наибольший среди значений с меньшим , и, аналогично для , наименьший среди больших.
Рассмотрим ключи. Порядок для них по
совпадает с их порядком. Тогда для некоторых и : , в таком случае и его и по . В таком случае среди них есть реальный или по доказанному, а понять, чем именно он является, мы можем просто сделав сравнение сПоиск реального следующего и предыдущего
Мы умеем находить реальный
и по и от , теперь покажем, как искать и от за . Определим как число, составленное из единиц и , то есть . Вычтем из число . В начале каждого блока, где , сохранятся единицы. Применим к получившемуся побитовое c , чтобы убрать лишние биты.
Если
, то , в противном случае . Теперь надо найти количество единиц в . Умножим на , тогда все единицы сложатся в первом блоке результата, и, чтобы получить количество единиц, сдвинем его вправо на бит. В таком случае мы получим некоторое , где является реальным , а мы можем получить с помощью цикла де БрёйнаИндекс наиболее старшего бита с помощью цикла де Брёйна
Последовательность де Брёйна — последовательность
, элементы которой принадлежат заданному конечному множеству (обычно рассматривают множество ), и все подпоследовательности заданной длины различны.Примеры
Примеры циклов де Брёйна для
с периодом :- (содержит подпоследовательности и )
- (содержит подпоследовательности )
Получение индекса по значению степени двойки
Возьмем цикл де Брёйна для
и запишем его как число (для цикл де Брёна равен , а значение ). Умножим это число на , сдвинем его влево на , а затем обратно вправо на ( такое, что ). ), тогда получившееся число — -ая подстрока длины данного цикла де Брёйна. Эту перестановку опозначим за и тогда применив ее к получим : в данном случае такое, что подряд идущих бит равны значению, на сколько мы сдвинули.Вычисление sketch(x)
Чтобы найти
за константное время, будем вычислять , имеющий все существенные биты в нужном порядке, но содержащий лишние нули. Хотя содержит лишние нули, мы сможем вычислять его быстрее, чем обычный , потому что нам не придется каждый раз идти по всем битам числа, выбирая стоящие на нужных нам местах. Будем использовать вместо — это никак не повлияет на сравнение, поскольку добавленные биты равны нулю и стоят на одних и тех же местах для всех- Уберем все несущественные биты .
- Умножением на некоторое заранее вычисленное число сместим все существенные биты в блок меньшего размера: .
- Применив побитовое , уберем лишние биты, появившиеся в результате умножения: .
- Сделаем сдвиг вправо на бит.
Утверждение: |
Дана последовательность из чисел . Тогда существует последовательность , такая что:
|
Выберем некоторые Чтобы получить , таким образом, чтобы . Предположим, что мы выбрали . Тогда . Всего недопустимых значений для , поэтому всегда можно найти хотя бы одно значение. , выбираем каждый раз наименьшее и прибавляем подходящее число кратное , такое что . |
Первые два условия необходимы для того, чтобы сохранить все существенные биты в нужном порядке. Третье условие позволит поместить
узла в -битный тип. Так как , то будет занимать бит, при всех