Изменения

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

Z-функция

863 байта добавлено, 19:01, 16 апреля 2016
Построение строки по Z-функции
Если строить строку по некорректному массиву значений Z-функции, то мы получим какую-то строку, но массив значений Z-функций от неё будет отличаться от исходного.
=== Время работы ===
Этот алгоритм работает за O(|S|), так как мы один раз проходим по массиву Z-функций.
=== Реализация ===
Данный алгоритм работает за <tex>O(n)</tex>.
'''string''' buildFromZ(z : '''int'''[], alphabet : '''char'''[]):
'''string''' s = ""
Пусть <tex>z</tex> — данная Z-функция, строку <tex>s</tex> построил наш алгоритм, <tex>q</tex> — массив значений Z-функции для <tex>s</tex>. Покажем, что массивы <tex>q</tex> и <tex>z</tex> будут совпадать.
Рассмотрим похожий алгоритм, но с более худшей асимптотикой[[Файл: Запись_префикса. Отличие будет в томpng|330px|thumb|right|Записали префикс, что при <tex>z[i] > 0</tex> мы будем писать префикс полностью и возвращаться начинающийся в позицию <tex>i + 1</tex>. Рассмотрим каждый шаг этого алгоритма. Если <tex>z[i] = 0</tex>, то мы После пишем символпрефикс, отличный от первого символа строки, поэтому начинающийся в <tex>q[i] = 0</tex>, а значит <tex>q[i] = z[i]j</tex>. Если <tex>z[i] > 0</tex>, то при записи <tex>s[i]</tex> мы будем получать <tex>q[i] = z[i]</tex>, потому что мы переписали Этот префикс строкине изменит символы первого префикса. Но далее мы можем переписать этот префикс другим префиксом. Заметим, что новый префикс будет содержаться и в префиксе самой строки. Поэтому пересечение двух префиксов будет состоять из одинаковых символов. Значит, префикс не будет изменяться, как и значение <tex>q[i]</tex>. Тогда массив <tex>q</tex> совпадает с <tex>z</tex>.]
Рассмотрим похожий алгоритм, но с более худшей асимптотикой. Отличие будет в том, что при <tex>z[i] > 0</tex> мы будем писать префикс полностью и возвращаться в позицию <tex>i + 1</tex>. Рассмотрим каждый шаг этого алгоритма. Если <tex>z[i] = 0</tex>, то мы пишем символ, отличный от первого символа строки, поэтому <tex>q[i] = 0</tex>, а значит <tex>q[i] = z[i]</tex>. Если <tex>z[i] > 0</tex>, то при записи <tex>s[i]</tex> мы будем получать <tex>q[i] = z[i]</tex>, потому что мы переписали префикс строки. Но далее мы можем переписать этот префикс другим префиксом. Заметим, что новый префикс будет содержаться и в префиксе самой строки, поэтому пересечение двух префиксов будет состоять из одинаковых символов. Значит, префикс не будет изменяться, как и значение <tex>q[i]</tex>. Тогда массив <tex>q</tex> совпадает с <tex>z</tex>. Покажем, что этот алгоритм эквивалентен нашему алгоритму. Когда мы пишем разные префиксы, то возможны три варианта: они не пересекаются(начало и конец одного префикса не принадлежат другому), один лежит внутри другого(начало и конец префикса принадлежит другому), они пересекаются(начало одного префикса пренадлежит другому, но конец не принадлежит).
* Если префиксы не пересекаются, то в алгоритме они не влияют друг на друга.
[[Файл: Префиксы1.png|400px]]
* Если префикс лежит внутри другого префикса, то записав большой префикс мы запишем и малый, поэтому не нужно возвращаться к началу малого префикса.
[[Файл: Префиксы2.png|400px]]
* Если префиксы пересекаются, то нам нужно переписать часть префикса, который начинается раньше, и начать писать другой префикс (начало этого префикса запишет конец префикса, начинающегося раньше).
[[Файл: Префиксы3.png|400px]]
Таким образом, алгоритмы эквивалентны и наш алгоритм тоже корректен.
146
правок

Навигация