Алгоритм Шибера-Вишкина — различия между версиями
Строка 1: | Строка 1: | ||
''Алгоритм Шибера-Вишкина'' применяется для нахождения [[Сведение задачи LCA к задаче RMQ|наименьшего общего предка]] (англ. ''least common ancestor'') двух вершин в дереве. | ''Алгоритм Шибера-Вишкина'' применяется для нахождения [[Сведение задачи LCA к задаче RMQ|наименьшего общего предка]] (англ. ''least common ancestor'') двух вершин в дереве. | ||
− | Он использует <tex>O(n)</tex> времени на | + | Он использует <tex>O(n)</tex> времени на препроцессинг и затем отвечает на каждый запрос за <tex>O(1)</tex>. |
==Идея алгоритма== | ==Идея алгоритма== | ||
Строка 8: | Строка 8: | ||
# Если дерево {{---}} полное двоичное дерево высоты <tex>h</tex>, то можно сопоставить каждой вершине битовый вектор длиной <tex>h</tex> (целое число от <tex>0</tex> до <tex>2^h-1</tex>) и с помощью битовых операций над этими векторами найти <tex>LCA(u, v)</tex> | # Если дерево {{---}} полное двоичное дерево высоты <tex>h</tex>, то можно сопоставить каждой вершине битовый вектор длиной <tex>h</tex> (целое число от <tex>0</tex> до <tex>2^h-1</tex>) и с помощью битовых операций над этими векторами найти <tex>LCA(u, v)</tex> | ||
− | Тогда, представив данное дерево как полное двоичное дерево, в некоторых вершинах которого находится простой путь, можно научиться искать <tex>LCA(v, u)</tex> в нем за <tex>O(1)</tex>. | + | Тогда, представив данное дерево как полное [[Дерево поиска, наивная реализация|двоичное дерево]], в некоторых вершинах которого находится простой путь, можно научиться искать <tex>LCA(v, u)</tex> в нем за <tex>O(1)</tex>. |
+ | |||
+ | ==Препроцессинг== | ||
+ | |||
− | |||
− | |||
− | |||
<tex>T</tex> {{---}} входное дерево с <tex>n</tex> вершинами. Для него нужно отвечать на запросы <tex>LCA</tex>.<br> | <tex>T</tex> {{---}} входное дерево с <tex>n</tex> вершинами. Для него нужно отвечать на запросы <tex>LCA</tex>.<br> | ||
− | <tex>B</tex> {{---}} полное двоичное дерево с не менее, чем <tex>n</tex> вершинами. Будет введено и объяснено дальше.<br> | + | <tex>B</tex> {{---}} полное [[Дерево поиска, наивная реализация|двоичное дерево]] с не менее, чем <tex>n</tex> вершинами. Будет введено и объяснено дальше.<br> |
<tex>u \in S(v)</tex> {{---}} вершина <tex>u</tex> находится в поддереве вершины <tex>v</tex>. Здесь и далее считаем, что вершина является и своим предком, и своим потомком.<br> | <tex>u \in S(v)</tex> {{---}} вершина <tex>u</tex> находится в поддереве вершины <tex>v</tex>. Здесь и далее считаем, что вершина является и своим предком, и своим потомком.<br> | ||
<tex>v</tex> ''выше'' <tex>u</tex> {{---}} то же самое, что <tex>u \in S(v)</tex>. Корень выше любой вершины. | <tex>v</tex> ''выше'' <tex>u</tex> {{---}} то же самое, что <tex>u \in S(v)</tex>. Корень выше любой вершины. | ||
− | + | ||
Перенумеруем вершины в порядке префиксного обхода дерева: сначала обрабатывается текущая вершина, затем {{---}} поддеревья. | Перенумеруем вершины в порядке префиксного обхода дерева: сначала обрабатывается текущая вершина, затем {{---}} поддеревья. | ||
− | Пусть <tex>\operatorname{order} : V \to \mathbb{N}</tex> {{---}} такой порядок обхода. | + | Пусть <tex>\operatorname{pre-order} : V \to \mathbb{N}</tex> {{---}} такой порядок обхода. |
Обозначим за <tex>\operatorname{size} v</tex> количество вершин в поддереве вершины <tex>v</tex>. | Обозначим за <tex>\operatorname{size} v</tex> количество вершин в поддереве вершины <tex>v</tex>. | ||
Строка 26: | Строка 26: | ||
{{Утверждение | {{Утверждение | ||
|statement=Пусть <tex>u \in S(v)</tex>. Тогда | |statement=Пусть <tex>u \in S(v)</tex>. Тогда | ||
− | <tex>\operatorname{order} u \in [\operatorname{order} v; \operatorname{order}v + \operatorname{size} v - 1]</tex> | + | <tex>\operatorname{pre-order} u \in [\operatorname{pre-order} v; \operatorname{pre-order}v + \operatorname{size} v - 1]</tex> |
|proof= | |proof= | ||
− | По определению <tex>\operatorname{order}</tex>, <tex>\operatorname{order} u</tex> вершин из поддерева <tex>v</tex> образуют | + | По определению <tex>\operatorname{pre-order}</tex>, <tex>\operatorname{pre-order} u</tex> вершин из поддерева <tex>v</tex> образуют |
отрезок натуральных чисел длиной <tex>\operatorname{size} v - 1</tex>. Так как этот отрезок начинается с | отрезок натуральных чисел длиной <tex>\operatorname{size} v - 1</tex>. Так как этот отрезок начинается с | ||
− | <tex>\operatorname{order}v + 1</tex>, то <tex>\operatorname{order} u</tex> лежит в отрезке <tex>[\operatorname{order} v; \operatorname{order} v + \operatorname{size} v - 1]</tex>. | + | <tex>\operatorname{pre-order}v + 1</tex>, то <tex>\operatorname{pre-order} u</tex> лежит в отрезке <tex>[\operatorname{pre-order} v; \operatorname{pre-order} v + \operatorname{size} v - 1]</tex>. |
}} | }} | ||
Строка 36: | Строка 36: | ||
{{Утверждение | {{Утверждение | ||
− | |statement=В качестве <tex>\operatorname{inlabel} v</tex> можно выбрать <tex>\operatorname{order} u</tex>, кратное максимальной степени двойки, где <tex>u \in S(v)</tex>. | + | |statement=В качестве <tex>\operatorname{inlabel} v</tex> можно выбрать <tex>\operatorname{pre-order} u</tex>, кратное максимальной степени двойки, где <tex>u \in S(v)</tex>. |
|proof= | |proof= | ||
− | Пусть <tex>\operatorname{inlabel} v = \operatorname{order} u = k2^b</tex>, <tex>b</tex> {{---}} максимально. | + | Пусть <tex>\operatorname{inlabel} v = \operatorname{pre-order} u = k2^b</tex>, <tex>b</tex> {{---}} максимально. |
− | Пусть есть вершина <tex>u' \in S(v)</tex> такая, что <tex>\operatorname{order} u' = k'2^b</tex>. | + | Пусть есть вершина <tex>u' \in S(v)</tex> такая, что <tex>\operatorname{pre-order} u' = k'2^b</tex>. |
Так как в отрезке, соответствующем вершине <tex>v</tex> есть два числа, кратных <tex>2^b</tex>, то | Так как в отрезке, соответствующем вершине <tex>v</tex> есть два числа, кратных <tex>2^b</tex>, то | ||
там есть и число, кратное <tex>2^{b+1}</tex>. Но тогда <tex>\operatorname{inlabel} v</tex> выбран неверно. | там есть и число, кратное <tex>2^{b+1}</tex>. Но тогда <tex>\operatorname{inlabel} v</tex> выбран неверно. | ||
− | Значит, в поддереве <tex>v</tex> есть только одна такая вершина <tex>u</tex>, что <tex>2^{max} | \operatorname{order} u</tex>. | + | Значит, в поддереве <tex>v</tex> есть только одна такая вершина <tex>u</tex>, что <tex>2^{max} | \operatorname{pre-order} u</tex>. |
Рассмотрим два случая. | Рассмотрим два случая. | ||
− | '''Первый случай''' <tex>\operatorname{inlabel} v = \operatorname{order} v</tex> | + | '''Первый случай''' <tex>\operatorname{inlabel} v = \operatorname{pre-order} v</tex> |
Других таких вершин <tex>u'</tex>, что <tex>u'</tex> дает такую же степень двойки, нет. | Других таких вершин <tex>u'</tex>, что <tex>u'</tex> дает такую же степень двойки, нет. | ||
Значит, во всех поддеревьях <tex>v</tex> значения <tex>\operatorname{inlabel}</tex> отличаются | Значит, во всех поддеревьях <tex>v</tex> значения <tex>\operatorname{inlabel}</tex> отличаются | ||
от <tex>\operatorname{inlabel} v</tex>. | от <tex>\operatorname{inlabel} v</tex>. | ||
− | '''Второй случай''' <tex>\operatorname{inlabel} v = \operatorname{order} u</tex>, <tex>u \in S(v), u \ne v</tex>. Так как в поддереве <tex>v</tex> представлены все <tex>\operatorname{order}</tex>-ы из отрезка <tex>[\operatorname{order} v; \operatorname{order} v + \operatorname{size} v - 1]</tex>, то рассмотрим того непосредственного потомка <tex>w</tex> вершины <tex>v</tex>, что <tex>u \in S(w)</tex>. Тогда, так как степень двойки у <tex>u</tex> максимальна, по утверждению в начале доказательства, других вершин с такой же степенью двойки нет, то <tex>\operatorname{inlabel} w = \operatorname{inlabel} v = \operatorname{order} u</tex>. Так как отрезки, соответствующие поддеревьям сыновей, не пересекаются, не найдется другого <tex>w'</tex> {{---}} потомок <tex>v</tex>, что в поддереве <tex>w'</tex> есть вершина с такой же степенью двойки. Значит, все вершины <tex>v'</tex>, у которых <tex>\operatorname{inlabel} v' = \operatorname{inlabel} v</tex> находятся в поддереве <tex>w</tex>. | + | '''Второй случай''' <tex>\operatorname{inlabel} v = \operatorname{pre-order} u</tex>, <tex>u \in S(v), u \ne v</tex>. Так как в поддереве <tex>v</tex> представлены все <tex>\operatorname{pre-order}</tex>-ы из отрезка <tex>[\operatorname{pre-order} v; \operatorname{pre-order} v + \operatorname{size} v - 1]</tex>, то рассмотрим того непосредственного потомка <tex>w</tex> вершины <tex>v</tex>, что <tex>u \in S(w)</tex>. Тогда, так как степень двойки у <tex>u</tex> максимальна, по утверждению в начале доказательства, других вершин с такой же степенью двойки нет, то <tex>\operatorname{inlabel} w = \operatorname{inlabel} v = \operatorname{pre-order} u</tex>. Так как отрезки, соответствующие поддеревьям сыновей, не пересекаются, не найдется другого <tex>w'</tex> {{---}} потомок <tex>v</tex>, что в поддереве <tex>w'</tex> есть вершина с такой же степенью двойки. Значит, все вершины <tex>v'</tex>, у которых <tex>\operatorname{inlabel} v' = \operatorname{inlabel} v</tex> находятся в поддереве <tex>w</tex>. |
Получили, что прообраз <tex>\operatorname{inlabel} v</tex> в вершине <tex>v</tex> или обрывается, или продолжается вниз ровно в одного потомка. Значит, прообраз <tex>\operatorname{inlabel} v</tex> {{---}} простой путь из какой-то вершины вниз в <tex>T</tex>, что и требовалось доказать. | Получили, что прообраз <tex>\operatorname{inlabel} v</tex> в вершине <tex>v</tex> или обрывается, или продолжается вниз ровно в одного потомка. Значит, прообраз <tex>\operatorname{inlabel} v</tex> {{---}} простой путь из какой-то вершины вниз в <tex>T</tex>, что и требовалось доказать. | ||
Строка 57: | Строка 57: | ||
{{Утверждение | {{Утверждение | ||
− | |statement=<tex>\operatorname{inlabel} v = 2^i \lfloor\frac{\operatorname{order} v + \operatorname{size} v}{2^i}\rfloor</tex>, где <tex>i = \lfloor\log_2 ((\operatorname{order} - 1) v \oplus (\operatorname{order} v + \operatorname{size} v - 1)) \rfloor + 1</tex> | + | |statement=<tex>\operatorname{inlabel} v = 2^i \lfloor\frac{\operatorname{pre-order} v + \operatorname{size} v}{2^i}\rfloor</tex>, где <tex>i = \lfloor\log_2 ((\operatorname{pre-order} - 1) v \oplus (\operatorname{pre-order} v + \operatorname{size} v - 1)) \rfloor + 1</tex> |
|proof= | |proof= | ||
− | Посмотрим на <tex>A = (\operatorname{order} v - 1) \oplus (\operatorname{order} v + \operatorname{size} v - 1)</tex>. | + | Посмотрим на <tex>A = (\operatorname{pre-order} v - 1) \oplus (\operatorname{pre-order} v + \operatorname{size} v - 1)</tex>. |
Посмотрим на позицию самго значимого единичного бита <tex>l</tex> в <tex>A</tex>. | Посмотрим на позицию самго значимого единичного бита <tex>l</tex> в <tex>A</tex>. | ||
− | Так как в <tex>\operatorname{order} v - 1</tex> там еще <tex>0</tex>, а в <tex>\operatorname{order} v + \operatorname{size} v - 1</tex> {{---}} уже единица, то в отрезке <tex>[\operatorname{order} v; \operatorname{order} v + \operatorname{size} v]</tex> есть число, кратное <tex>2^l</tex>. | + | Так как в <tex>\operatorname{pre-order} v - 1</tex> там еще <tex>0</tex>, а в <tex>\operatorname{pre-order} v + \operatorname{size} v - 1</tex> {{---}} уже единица, то в отрезке <tex>[\operatorname{pre-order} v; \operatorname{pre-order} v + \operatorname{size} v]</tex> есть число, кратное <tex>2^l</tex>. |
Докажем, что нет чисел, кратных <tex>2^{l+1}</tex>. Пусть такое число нашлось. Тогда <tex>l</tex>-й бит менялся хотя бы два раза, а значит, менялся | Докажем, что нет чисел, кратных <tex>2^{l+1}</tex>. Пусть такое число нашлось. Тогда <tex>l</tex>-й бит менялся хотя бы два раза, а значит, менялся | ||
− | <tex>l+1</tex>-й бит. А значит, самый значащий отличающийся бит в <tex>\operatorname{order} v - 1</tex> и в <tex>\operatorname{order} v + \operatorname{size} v - 1</tex> больше, чем <tex>l</tex>-й. | + | <tex>l+1</tex>-й бит. А значит, самый значащий отличающийся бит в <tex>\operatorname{pre-order} v - 1</tex> и в <tex>\operatorname{pre-order} v + \operatorname{size} v - 1</tex> больше, чем <tex>l</tex>-й. |
Заметим, что функция <tex>\lfloor \log_2 a \rfloor + 1</tex> просто выделяет номер самого значашего единичного бита. | Заметим, что функция <tex>\lfloor \log_2 a \rfloor + 1</tex> просто выделяет номер самого значашего единичного бита. |
Версия 22:56, 26 февраля 2016
Алгоритм Шибера-Вишкина применяется для нахождения наименьшего общего предка (англ. least common ancestor) двух вершин в дереве. Он использует времени на препроцессинг и затем отвечает на каждый запрос за .
Содержание
Идея алгоритма
Основная идея алгоритма следующая.
- Если бы дерево, в котором нужно искать было бы простым путем, можно было бы найти просто взяв ту вершину, которая находится в дереве ближе к корню.
- Если дерево — полное двоичное дерево высоты , то можно сопоставить каждой вершине битовый вектор длиной (целое число от до ) и с помощью битовых операций над этими векторами найти
Тогда, представив данное дерево как полное двоичное дерево, в некоторых вершинах которого находится простой путь, можно научиться искать в нем за .
Препроцессинг
— полное двоичное дерево с не менее, чем вершинами. Будет введено и объяснено дальше.
— вершина находится в поддереве вершины . Здесь и далее считаем, что вершина является и своим предком, и своим потомком.
выше — то же самое, что . Корень выше любой вершины.
Перенумеруем вершины в порядке префиксного обхода дерева: сначала обрабатывается текущая вершина, затем — поддеревья.
Пусть — такой порядок обхода.
Обозначим за
количество вершин в поддереве вершины .Утверждение: |
Пусть . Тогда
|
По определению , вершин из поддерева образуют отрезок натуральных чисел длиной . Так как этот отрезок начинается с , то лежит в отрезке . |
Покроем дерево путями. А именно, сопоставим каждой вершине
число такое, что прообраз каждого в связен и является простым путем от какой-то вершины вниз до листа.Утверждение: |
В качестве можно выбрать , кратное максимальной степени двойки, где . |
Пусть , — максимально. Пусть есть вершина такая, что . Так как в отрезке, соответствующем вершине есть два числа, кратных , то там есть и число, кратное . Но тогда выбран неверно. Значит, в поддереве есть только одна такая вершина , что .Рассмотрим два случая. Первый случай Других таких вершин , что дает такую же степень двойки, нет. Значит, во всех поддеревьях значения отличаются от .Второй случай Получили, что прообраз , . Так как в поддереве представлены все -ы из отрезка , то рассмотрим того непосредственного потомка вершины , что . Тогда, так как степень двойки у максимальна, по утверждению в начале доказательства, других вершин с такой же степенью двойки нет, то . Так как отрезки, соответствующие поддеревьям сыновей, не пересекаются, не найдется другого — потомок , что в поддереве есть вершина с такой же степенью двойки. Значит, все вершины , у которых находятся в поддереве . в вершине или обрывается, или продолжается вниз ровно в одного потомка. Значит, прообраз — простой путь из какой-то вершины вниз в , что и требовалось доказать. |
Утверждение: |
, где |
Посмотрим на . Посмотрим на позицию самго значимого единичного бита в .Так как в там еще , а в — уже единица, то в отрезке есть число, кратное .Докажем, что нет чисел, кратных . Пусть такое число нашлось. Тогда -й бит менялся хотя бы два раза, а значит, менялся -й бит. А значит, самый значащий отличающийся бит в и в больше, чем -й.Заметим, что функция просто выделяет номер самого значашего единичного бита.Функция Чтобы получить из отрезка число, кратное обнуляет все биты младше -го. , будучи уверенными, что оно там есть, достаточно обнулить битов в правой границе отрезка. |
Каждое значение
соответствует вершине в полном двоичном дереве высоты . В дереве на одном наборе вершин будет построено два набора ребер: каркасные и основные. Для каждой вершины с уровня, кроме последнего, будут каркасные ребра и . Таким образом, вершины в будут занумерованы в инфиксном порядке обхода по каркасным ребрам: сначала обрабатывается левое поддерево, потом — вершина, потом — правое поддерево. В будет основное ребро между вершинами и , если в есть ребро . Корень имеет номер . Будем говорить, что вершина лежит в поддереве вершины ( ), если от есть путь до по каркасным ребрам.Утверждение: |
Если в есть ребро , то в :
Другими словами, все основные ребра направлены вниз. |
Посчитаем для каждого
множество всех его потомков в по основным ребрам. Заметим, что для хранения одного потомка достаточно хранить только его высоту в дереве. Чтобы восстановить его значение, нужно просто подняться на вверх от вершины . Поэтому, все это множество можно уместить в целое число: -й бит будет единицей, если есть потомок на высоте . Назовем это число, отвечающее множеству предков, .В дальнейшем
поможет в поиске . Также, нам понадобится еще следующая информация. — самая не глубокая вершина такая, что . — глубина вершины в .Обработка запроса
Пусть
, — вершины в исходном дереве которых необходимо найти. Если , то они принадлежат одному простому пути, а следовательно ответом на запрос является , если , и , в противном случае. Теперь рассмотрим случай, когда , то есть и принадлежат разным простым путям.Утверждение: |
Следующие вычисления позволяют найти :
|
и — вершины в . Биты в их записи задают задают их местоположение в дереве. Ноль — спуститься влево, единица — спуститься вправо или остаться здесь. Значит, наиболее значимый бит побитового исключающего или их номеров даст глубину, на которой пути до этих вершин начинают расходиться. Это и хранится в . Значит, мы нашли Взяв побитовое и по каркасным ребрам. Однако, могло случиться так, что по основным ребрам, поиском которого мы занимаемся, находится выше (он не может находиться ниже или в стороне, так как все основные ребра направлены вниз). и , в старших единичных битах мы получим путь от корня по основным ребрам до этих вершин. При этом, про те биты, которые отвечают за уровни ниже , ничего не известно. Поэтому, нужно их обнулить. Умножение и деление на обнулят ненужные биты. После этого, для нахождения по основным ребрам, нужно найти в наименее значимый единичный бит. Формула имеено это и делает. |
После этих действий нами был получен путь, в котором находится ответ. Осталось посмотреть на точки входа
и на путь . Это можно сделать с помощью посчитанной функции : найти , где — вершина предпоследнего пути в пути. Тогда, поднявшись от нее на один вверх по начальному дереву, получим искомую точку входа.Имея две точки входа, можно, как и в первом случае, сравнить их по высоте и выбрать более высокое из них.
Оценка сложности
Построение
Подсчет каждого из массивов занимает
. Это можно сделать, например, обходом в глубину.Запрос
Здесь нужно сделать
действий для ответа на запрос.