Изменения

Перейти к: навигация, поиск

Алгоритм Шибера-Вишкина

2720 байт добавлено, 19:07, 4 сентября 2022
м
rollbackEdits.php mass rollback
'''Алгоритм Шибера-Вишкина'' ' (англ.''Schieber-Vishkin '') применяется для нахождения [[Сведение задачи LCA к задаче RMQ|наименьшего общего предка ]] двух вершин в дереве.Он использует <tex>O(n)</tex> времени на подготовку препроцессинг и затем отвечает на каждый запрос за <tex>O(1)</tex>.
==Идея алгоритма==
Основная идея алгоритма следующая.
# Если бы дерево, в котором нужно искать <tex>LCA</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>\operatorname{order} : V \to \mathbb{N}</tex> {{---}} такой порядок обхода.
Обозначим за <tex>T</tex> {{---}} входное дерево с <tex>n</tex> вершинами. Для него нужно отвечать на запросы <tex>LCA</tex>.<br><tex>B</tex>\operatorname{size{---}} полное [[Дерево поиска, наивная реализация|двоичное дерево]] с не менее, чем <tex>n</tex> вершинами. Будет введено и объяснено дальше.<br><tex>S(v)</tex> количество вершин в поддереве {{---}} поддерево вершины <tex>v</tex>. Здесь и далее считаем, что вершина является и своим предком, и своим потомком.<br><tex>v</tex> ''выше'' <tex>u</tex> {{---}} то же самое, что <tex>u \in S(v)</tex>. Корень выше любой вершины. Перенумеруем вершины в порядке [[Дерево поиска, наивная реализация|префиксного обхода дерева]]. Обозначим за <tex>\operatorname{size} v</tex> количество вершин в поддереве вершины <tex>v</tex>.
{{Утверждение
|statement=Пусть <tex>u</tex> {{---}} вершина из поддерева <tex>\in S(v)</tex>. Тогда <tex>\operatorname{orderpreOrder} u \in [\operatorname{orderpreOrder} v; \operatorname{orderpreOrder}v + \operatorname{size} v - 1]</tex>
|proof=
По определению <tex>\operatorname{orderpreOrder}</tex>, : <tex>\operatorname{orderpreOrder} u</tex> вершин из поддерева <tex>v</tex> образуют
отрезок натуральных чисел длиной <tex>\operatorname{size} v - 1</tex>. Так как этот отрезок начинается с
<tex>\operatorname{orderpreOrder}v + 1</tex>, то <tex>\operatorname{orderpreOrder} u</tex> {{---}} отрезок лежит в отрезке <tex>[\operatorname{orderpreOrder} v; \operatorname{orderpreOrder} v + \operatorname{size} v - 1]</tex>.
}}
{{Утверждение
|statement=В качестве <tex>\operatorname{inlabel} v</tex> можно выбрать <tex>\operatorname{orderpreOrder} u</tex>, кратное максимальной степени двойки, где <tex>u \in S(v)</tex>.
|proof=
Пусть <tex>\operatorname{inlabel} v = \operatorname{orderpreOrder} u = k2^b</tex>, <tex>b</tex> {{---}} максимально.Пусть есть вершина <tex>u' \in S(iv)</tex> такая, что <tex>\operatorname{orderpreOrder} u' = k'2^b</tex>.
Так как в отрезке, соответствующем вершине <tex>v</tex> есть два числа, кратных <tex>2^b</tex>, то
там есть и число, кратное <tex>2^{b+1}</tex>. Но тогда <tex>\operatorname{inlabel} v</tex> выбран неверно.
Значит, в поддереве <tex>v</tex> есть только одна такая вершина <tex>u</tex>, что <tex>2^{max} | \operatorname{orderpreOrder} u \hdots 2^{max}</tex>.
Рассмотрим два случая.
'''Первый случай''' : <tex>\operatorname{inlabel} v = \operatorname{orderpreOrder} v</tex>.&nbsp; Других таких вершин <tex>u'</tex>, что <tex>u'</tex> дает такую же степень двойки, нет.
Значит, во всех поддеревьях <tex>v</tex> значения <tex>\operatorname{inlabel}</tex> отличаются
от <tex>\operatorname{inlabel} v</tex>.
'''Второй случай''' : <tex>\operatorname{inlabel} v = \operatorname{orderpreOrder} u</tex>, <tex>u \in S(v), u \ne v</tex>. Так как в поддереве <tex>v</tex> представлены все <tex>\operatorname{orderpreOrder}</tex>-ы из отрезка <tex>[\operatorname{orderpreOrder} v; \operatorname{orderpreOrder} 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{orderpreOrder} 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>wв вершине <tex>v</tex> или обрывается, или продолжается вниз ровно в одного потомка. Значит, прообраз <tex>\operatorname{inlabel} v</tex> {{---}} простой путь из какой-то вершины вниз в <tex>T</tex>, получим требуемоечто и требовалось доказать.
}}
{{Утверждение
|statement=<tex>\operatorname{inlabel} v = 2^i (\fracbigg\lfloor \dfrac{\operatorname{orderpreOrder} v + \operatorname{size} v}{2^i})\bigg\rfloor</tex>, где <tex>i = \lfloor\log_2 ((\operatorname{orderpreOrder} v - 1) \oplus (\operatorname{orderpreOrder} v + \operatorname{size} v- 1)) \rfloor + 1</tex>
|proof=
Посмотрим на <tex>A = (\operatorname{orderpreOrder} v - 1) \oplus (\operatorname{orderpreOrder} v + \operatorname{size} v- 1)</tex>. Посмотрим на позицию самой правой единицы самого значимого единичного бита <tex>l</tex> в <tex>A</tex>.
Так как в <tex>\operatorname{orderpreOrder} v- 1</tex> там еще <tex>0</tex>, а в <tex>\operatorname{orderpreOrder} v + \operatorname{size} v- 1</tex> {{---}} уже единица, то в отрезке <tex>[\operatorname{orderpreOrder} v; \operatorname{orderpreOrder} v + \operatorname{size} v]</tex> есть число, кратное <tex>2^l</tex>.
Докажем, что нет чисел, кратных <tex>2^{l+1}</tex>. Пусть такое число нашлось. Тогда <tex>l</tex>-й бит менялся хотя бы два раза, а значит, менялся
<tex>l+1</tex>-й бит. А значит, самый значащий отличающийся бит в <tex>\operatorname{orderpreOrder} v- 1</tex> и в <tex>\operatorname{orderpreOrder} v + \operatorname{size} v- 1</tex> больше, чем <tex>l</tex>-й.
Заметим, что функция <tex>\lfloor \log_2 a \rfloor + 1</tex> просто выделяет номер самого значашего единичного бита.
Функция <tex>2^l\fracleft\lfloor\dfrac{a}{2^l}\right\rfloor</tex> обнуляет все биты младше <tex>l</tex>-го.
Чтобы получить из отрезка число, кратное <tex>2^l</tex>, будучи уверенными, что оно там есть, достаточно обнулить <tex>l</tex> битов в правой границе отрезка.
}}
Каждое значение <tex>\operatorname{inlabel} v</tex> соответствует вершине в полном двоичном дереве <tex>B</tex> высоты <tex>h=\lceil\log_2 n\rceil</tex>. В двоичном дереве будем нумеровать на одном наборе вершин будет построено два набора ребер: ''каркасные'' и ''основные''. Для каждой вершины <tex>v \in V(B)</tex> с уровня, кроме последнего, будут каркасные ребра <tex>v\to2v</tex> и <tex>v\to2v+1</tex>. Таким образом, вершины в <tex>B</tex> будут занумерованы в инфиксном порядкеобхода по каркасным ребрам: обойдем сначала обрабатывается левое поддерево, занумеруем вершинупотом {{---}} вершина, обойдем потом {{---}} правое поддерево. В двоичном дереве <tex>B</tex> будет основное ребро между вершинами <tex>\operatorname{inlabel} v</tex> и <tex>\operatorname{inlabel} u</tex>, если в начальном дереве <tex>T</tex> есть ребро <tex>v\to u</tex>. Стандартных для двоичного дереваребер не будетКорень имеет номер <tex>1</tex>. Они нужны только для тогоБудем говорить, чтобы занумеровать что вершина <tex>u \in B</tex> лежит в поддереве вершины и для следующего утверждения<tex>u \in B</tex> (<tex>u \in S(v)</tex>), если от <tex>v</tex> есть путь до <tex>u</tex> по каркасным ребрам.
{{Утверждение
|statement=Если в начальном дереве <tex>T</tex> есть ребро <tex>v\to u</tex> (, то в <tex>u \in S(v)B</tex>), то в построенном двоичном дереве: <tex>\operatorname{inorderinlabel} u \in S(\operatorname{inorderinlabel} v)</tex>Другими словами, все основные ребра направлены вниз.
|proof=
}}
Посчитаем для каждого <tex>\operatorname{inlabel} v</tex> множество всех его потомков предков в двоичном дереве<tex>B</tex> по основным ребрам. Заметим, что для хранения одного потомка предка достаточно хранить только его высоту в дереве. Чтобы восстановить его значение, нужно просто подняться на <tex>\Delta h</tex> вверх от вершины <tex>v</tex>. Поэтому, все это множество можно уместить вцелое число: <tex>i</tex>-й бит будет единицей, если есть потомок предок на высоте <tex>i</tex>. Назовем это число , отвечающее множеству предков, <tex>\operatorname{ascendant} v</tex>.
В дальнейшем <tex>\operatorname{ascendant} v </tex> поможет в поиске <tex>LCA(\operatorname{inlabel} v, \operatorname{inlabel} u)</tex>. Также, нам понадобится еще следующая информация. <tex>\operatorname{head} v</tex> {{---}} самая не глубокая вершина <tex>u</tex> такая, что <tex>\operatorname{inlabel} v = \operatorname{inlabel} u</tex>. <tex>\operatorname{level} v</tex> {{---}} глубина вершины <tex>v</tex> в <tex>T</tex>.
==Обработка запроса==
Пусть <tex>x</tex>, <tex>y</tex> {{---}} вершины в исходном дереве <tex>LCA</tex> которых необходимо найти. Если <tex>\operatorname{inlabel} x = \operatorname{inlabel} y</tex>, то они принадлежат одному простому пути, а следовательно ответом на запрос является <tex>x</tex>, если <tex>\operatorname{level} x \le leqslant \operatorname{level} y</tex>, и <tex>y</tex>, в противном случае. Теперь рассмотрим случай, когда <tex>\operatorname{inlabel} x \ne \operatorname{inlabel} y</tex>, то есть <tex>x</tex> и <tex>y</tex> принадлежат разным простым путям. Найдем <tex>b = LCA(\operatorname{inlabel} x, \operatorname{inlabel} y)</tex>.
{{Утверждение
|statement= Следующие вычисления позволяют найти <tex>LCA(\operatorname{inlabel} LCA(x, \operatorname{inlabel} y) = 2^i((2(\frac x{2^{i+1}})) \,|\, 1)</tex>, где : #<tex>i = \loglfloor\log_2 (\operatorname{inlabel} x \oplus \operatorname{inlabel} y)\rfloor</tex>|proof= Пусть #<tex>path = 2^i</tex> \lfloor\dfrac{(\operatorname{---ascendant}} индекс самой правой единицы в двоичном представлении <tex>b</tex>. Из того, что <tex>b</tex> общий предок <tex>x) \wedge (\operatorname{inlabelascendant} y)}{2^i} x\rfloor</tex> и #<tex>\operatorname{inlabel} LCA(x, y</tex> в полном двоичном дереве следует, что <tex>l) = \lfloor\dfrac12(path \oplus (path -i1))\rfloor + 1</tex> левых бит, совпадающих в |proof=<tex>\operatorname{inlabel} x</tex> и <tex>\operatorname{inlabel} y</tex>, должны быть такими же и {{---}} вершины в <tex>bB</tex>. Биты в их записи задают задают их местоположение в дереве.Ноль {{---}} спуститься влево, единица {{---}} спуститься вправо или остаться здесь. Значит, а так как наиболее значимый бит побитового исключающего или их номеров даст глубину, на которой пути до этих вершин начинают расходиться. Это и хранится в <tex>bi</tex> наименьший общий предок. Значит, то мы нашли <tex>iLCA</tex> {{---}} минимальный такой индекспо каркасным ребрам. То есть Однако, могло случиться так, что <tex>iLCA</tex> самый левый битпо основным ребрам, поиском которого мы занимаемся, находится выше (он не может находиться ниже или в котором различаются стороне, так как все основные ребра направлены вниз).  Взяв побитовое и <tex>\operatorname{inlabelascendant} x</tex> и <tex>\operatorname{inlabelascendant} y</tex>, в старших единичных битах мы получим путь от корня по основным ребрам до этих вершин. А двоичное представление При этом, про те биты, которые отвечают за уровни ниже <tex>bLCA</tex> состоит из , ничего не известно. Поэтому, нужно их обнулить. Умножение и деление на <tex>l-2^i</tex> левых бит обнулят ненужные биты. После этого, для нахождения <tex>\operatorname{inlabel} xLCA</tex> (или по основным ребрам, нужно найти в <tex>\operatorname{inlabel} ypath</tex>), единички и наименее значимый единичный бит. Формула <tex>i\dfrac12(x \oplus (x - 1)) + 1</tex> нулейимеено это и делает.
}}
Найдем вершину <tex>\operatorname{inorder} z</tex>, где <tex>z = LCA(x, y)</tex>. На прошлом шаге была найдена вершина
<tex>LCA(\operatorname{inlabel} x, \operatorname{inlabel} y)</tex>. Если бы в двоичном дереве были представлены все вершины,
то это и было бы ответом. Но такой вершины может не оказаться. Воспользуемся значениями <tex>\operatorname{ascendant} \operatorname{inlabel} x</tex> и <tex>\operatorname{ascendant} \operatorname{inlabel} y</tex>. Они характеризуют пути
из вершин <tex>\operatorname{inlabel} x</tex> и <tex>\operatorname{inlabel} x</tex> к корню. С их помощью (с помощью
операции ''логическое и''), можно получить список вершин, через которые проходят оба эти пути и взять с пересечения
самую низкую посещаемую обоими.
 
Для этого можно воспользоваться описанным при построении методом для нахождения <tex>\operatorname{inlabel} v</tex>.
После этих действий нами был получен путь, в котором находится ответ. Осталось посмотреть на точки входа
<tex>x</tex> и <tex>y</tex> на путь <tex>\operatorname{inlabel} LCA(x, y)</tex>.
Это можно сделать с помощью посчитанной функции <tex>\operatorname{head}</tex>: найти <tex>\operatorname{head} v'</tex>, где <tex>v'</tex> {{---}} вершина предпоследнего пути в пути. Тогда, поднявшись от нее на один вверх по начальному дереву, получим искомую точку входа.
Имея две точки входа, можно, как и в первом случае, сравнить их по высоте и выбрать более высокое из них.
==Оценка сложности==
===Построение===
Подсчет каждого из массивов <tex> \operatorname{inlabel} </tex> и <tex> \operatorname{preOrder}</tex> занимает <tex>O(n)</tex>. Это : <tex> \operatorname{preOrder}</tex> можно сделатьпосчитать, например, [[Обход в глубину, цвета вершин|обходом в глубину]], а <tex> \operatorname{inlabel} </tex> выражается через <tex> \operatorname{preOrder}</tex>, как описано выше.
===Запрос===
Здесь <tex>\operatorname{inlabel} LCA(x, y)</tex> и <tex>\operatorname{head} v'</tex> вычисляются за <tex>O(1)</tex>, следовательно, нужно сделать <tex>O(1)</tex> действий для ответа на запрос. == См.также ==*[[Алгоритм Тарьяна поиска LCA за O(1) в оффлайн ]]*[[Метод двоичного подъема]]== Источники информации ==* [http://ia600208.us.archive.org/12/items/onfindinglowe00schi/onfindinglowe00schi.pdf Baruch Schieber, Uzi Vishkin, "On Finding Lowest Common Ancestors: Simplification and Parallelization"] [[Категория: Дискретная математика и алгоритмы]][[Категория: Задача о наименьшем общем предке]]
1632
правки

Навигация