Префикс-функция
Префикс-функция строки
— функция .Алгоритм
Наивный алгоритм вычисляет префикс функцию непосредственно по определению, сравнивая префиксы и суффиксы строк.
Псевдокод
Prefix_function () [1..n] = 0 for i = 1 to n for k = 1 to i - 1 if s[1..k] == s[i - k + 1..i] [i] = k return
Пример
Рассмотрим строку abcabcd, для которой значение префикс-функции равно
.Шаг | Строка | Значение функции |
---|---|---|
a | 0 | |
ab | 0 | |
abc | 0 | |
abca | 1 | |
abcab | 2 | |
abcabc | 3 | |
abcabcd | 0 |
Время работы
Всего
итераций цикла, на каждой из который происходит сравнение строк за , что дает в итоге .Оптимизация
Вносятся несколько важных замечаний:
- Следует заметить, что . Действительно, если , тогда , значит в не максимально возможное значение, получено противоречие.
- Нужно избавиться от явных сравнений строк. Пусть вычислено и , тогда . Если отличается от , то нужно найти наибольшую длину , для которой верно . Когда найдется такое достаточно будет сравнить и , при их равенстве будет верно. Итеративно продолжается поиск , пока оно больше нуля. Если , то при значение , иначе нулю. Общая схема алгоритма есть, теперь нужно научиться искать .
- За исходное нужно взять , что следует из первого пункта. Как видно из рисунка, приведенного ниже, при совпадении символов и длина наибольшего общего префикса увеличивается на единицу. В случае, когда символы и не совпадают, — следующая по максимальности длина потенциального наибольшего общего префикса, что тоже понятно из рисунка. Последнее утверждение верно, пока , что позволит всегда найти его следующее значение.
Псевдокод
Prefix_function () [1] = 0 k = 0 for i = 2 to n 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.