Префикс-функция — различия между версиями
(→Время работы) |
(→Время работы) |
||
Строка 55: | Строка 55: | ||
===Время работы=== | ===Время работы=== | ||
− | С помощью [[Амортизационный анализ|метода потенциалов]] можно показать, что время работы <tex>O(n)</tex>. Потенциал величины <tex>k</tex> связывается с текущим ее значением в алгоритме. Начальное значение этого потенциала равно нулю. На каждой итерации цикла <tex>while</tex> значение <tex>k</tex> уменьшается, поскольку <tex>\pi(k) < k</tex>. Поскольку <tex>\pi(k) \ge 0</tex> значение этой переменной не бывает отрицательным. Также значение <tex>k</tex> изменяется не более чем на 1 внутри тела цикла <tex>for</tex>. Поскольку перед входом в цикл выполняется <tex> k < i</tex> и поскольку значение переменной <tex>i</tex> увеличивается в каждой итерации цикла <tex>for</tex>, справедливость неравенства <tex>k < i</tex> сохраняется (подтверждая тот факт, что соблюдается также неравенство <tex>\pi(i) < i </tex>. Каждое выполнение тела цикла <tex>while</tex> можно оплатить соответствующим уменьшение потенциальной функции, поскольку <tex>\pi(k) < k </tex>. Кроме этого значение потенциальной функции возрастает не более чем на 1, из-за этого амортизированная стоимость тела цикла <tex>for</tex> {{---}} <tex>O(1)</tex>. Так как количество итераций <tex>O(n)</tex>, и поскольку конечное значение потенциальной функции по величине не меньше, чем ее начальное значение, полное время работы в наихудшем случае равно <tex>O(n)</tex>. | + | С помощью [[Амортизационный анализ|метода потенциалов]] можно показать, что время работы <tex>O(n)</tex>. Потенциал величины <tex>k</tex> связывается с текущим ее значением в алгоритме. Начальное значение этого потенциала равно нулю. На каждой итерации цикла <tex>while</tex> значение <tex>k</tex> уменьшается, поскольку <tex>\pi(k) < k</tex>. Поскольку <tex>\pi(k) \ge 0</tex> значение этой переменной не бывает отрицательным. Также значение <tex>k</tex> изменяется не более чем на 1 внутри тела цикла <tex>for</tex>. Поскольку перед входом в цикл выполняется <tex> k < i</tex> и поскольку значение переменной <tex>i</tex> увеличивается в каждой итерации цикла <tex>for</tex>, справедливость неравенства <tex>k < i</tex> сохраняется (подтверждая тот факт, что соблюдается также неравенство <tex>\pi(i) < i </tex>. Каждое выполнение тела цикла <tex>while</tex> можно оплатить соответствующим уменьшение потенциальной функции, поскольку <tex>\pi(k) < k </tex>. Кроме этого значение потенциальной функции возрастает не более чем на 1, из-за этого [[Амортизационный анализ|амортизированная стоимость]] тела цикла <tex>for</tex> {{---}} <tex>O(1)</tex>. Так как количество итераций <tex>O(n)</tex>, и поскольку конечное значение потенциальной функции по величине не меньше, чем ее начальное значение, полное время работы в наихудшем случае равно <tex>O(n)</tex>. |
== Литература == | == Литература == | ||
Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ. {{---}} 2-е изд. {{---}} М.: Издательский дом «Вильямс», 2007. {{---}} С. 1296. | Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ. {{---}} 2-е изд. {{---}} М.: Издательский дом «Вильямс», 2007. {{---}} С. 1296. |
Версия 13:36, 9 июня 2012
Префикс-функция строки
— функция .Содержание
Алгоритм
Наивный алгоритм вычисляет префикс функцию непосредственно по определению, сравнивая префиксы и суффиксы строк.
Пример
Рассмотрим строку abcabcd, для которой значение префикс-функции равно
.Шаг | Строка | Значение функции |
---|---|---|
a | 0 | |
ab | 0 | |
abc | 0 | |
abca | 1 | |
abcab | 2 | |
abcabc | 3 | |
abcabcd | 0 |
Псевдокод
Prefix_function () [1]=0 for i = 2 to n for k = 1 to i - 1 if s[1..k] == s[i - k + 1..i] [i] = k return
Время работы
Всего
итераций цикла, на каждой из который происходит сравнение строк за , что дает в итоге .Оптимизация
Внесем несколько важных замечаний:
- превосходит не больше, чем на . Действительно, если , тогда , значит в не максимально возможное значение, получили противоречие.
- Избавимся от явных сравнений строк. Пусть мы вычислили и , тогда очевидно . Если отличается от , то нужно найти наибольшую длину , для которой верно . Когда мы найдем такое нам достаточно будет сравнить и , при их равенстве будет верно. Будем искать наше пока оно больше нуля, при равенстве нулю , если , иначе нулю. Общая схема алгоритма у нас есть, теперь нужно только научиться искать .
- Очевидно, что за исходное нужно взять . Как видно из рисунка, приведенного ниже, при совпадении символов и длина наибольшего общего префикса увеличивается на единицу. В случае, когда символы и не совпадают, — следующая по максимальности длина потенциального наибольшего общего префикса, что тоже понятно из рисунка. Последнее утверждение продолжается по индукции, и получается требуемый поиск
Псевдокод
Prefix_function () [1] = 0 for i = 2 to n k = [i - 1] while k > 0 && s[i] != s[k + 1] k = [k] if s[i] == s[k + 1] k++ [i] = k return
Время работы
С помощью метода потенциалов можно показать, что время работы . Потенциал величины связывается с текущим ее значением в алгоритме. Начальное значение этого потенциала равно нулю. На каждой итерации цикла значение уменьшается, поскольку . Поскольку значение этой переменной не бывает отрицательным. Также значение изменяется не более чем на 1 внутри тела цикла . Поскольку перед входом в цикл выполняется и поскольку значение переменной увеличивается в каждой итерации цикла , справедливость неравенства сохраняется (подтверждая тот факт, что соблюдается также неравенство . Каждое выполнение тела цикла можно оплатить соответствующим уменьшение потенциальной функции, поскольку . Кроме этого значение потенциальной функции возрастает не более чем на 1, из-за этого амортизированная стоимость тела цикла — . Так как количество итераций , и поскольку конечное значение потенциальной функции по величине не меньше, чем ее начальное значение, полное время работы в наихудшем случае равно .
Литература
Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ. — 2-е изд. — М.: Издательский дом «Вильямс», 2007. — С. 1296.