- •Элементарные алгоритмы для работы с графами
- •Работа алгоритма[править | править вики-текст]
- •Неформальное описание[править | править вики-текст]
- •Формальное описание[править | править вики-текст]
- •Алгоритм поиска в глубину[править | править вики-текст]
- •Нерекурсивные варианты[править | править вики-текст]
- •Общая идея
- •[Править]Пошаговое представление
- •[Править]Реализация
- •[Править]Время работы
- •[Править]Цвета вершин
- •Топологическая сортировка и сильно связные компоненты
- •↑ Пример ориентированного неотсортированного графа, к которому применима топологическая сортировка
- •Пример работы алгоритма[править | править вики-текст]
- •Алгоритмы[править | править вики-текст]
- •Минимальные остовные деревья (мst)
- •Введение
- •Постановка задачи
- •Кратчайшие пути
- •Давайте придумаем что-нибудь простое
- •А если я педант?
- •Задача о максимальном потоке
- •[Править]Определение потока
- •[Править]Пример
- •Увеличивающие пути. Теорема Бержа
- •Алгоритм Эдмондса. Сжатие цветков
- •Эффективная реализация
- •Оптимизация: предварительное построение паросочетания
- •Случай двудольного графа
- •Дальнейшая оптимизация
- •[Править]Реализация
- •[Править]Оценка производительности
- •[Править]Пример несходящегося алгоритма
- •[Править]Оценка быстродействия
- •[Править]Литература
- •Максимальные паросочетания[править | править вики-текст]
- •Описание алгоритма Необходимые определения
- •Теорема Бержа
- •Алгоритм Куна
- •Время работы
- •Реализация
- •Улучшенная реализация
- •[Править]Постановка задачи
- •[Править]Решение
- •[Править]Псевдокод
- •Префиксы и суффиксы строки
- •Прямые переходы
- •[Править]Суффиксные ссылки
- •Основные определения и описание структуры[править | править вики-текст]
- •Свойства суффиксных деревьев[править | править вики-текст]
- •Требования суффиксного дерева к памяти[править | править вики-текст]
- •[Править]Недостатки
- •Метод хеширования
- •[Править]Алгоритм
- •[Править]Псевдокод
- •[Править]Время работы
- •[Править]Надёжность
- •Автоматные модели в программировании
- •[Править]Переходы между состояниями [править]Прямые переходы
- •[Править]Суффиксные ссылки
- •[Править]Псевдокод
- •[Править]Пример использования
- •[Править]Псевдокод
- •[Править]Пример
- •[Править]Время работы
- •[Править]Эффективный алгоритм
- •[Править]Псевдокод
- •[Править]Время работы
- •[Править]Построение префикс-функции по z-функции [править]Постановка задачи
- •[Править]Описание алгоритма
- •Приближенные алгоритмы решения np-трудных задач
[Править]Пример использования
Строка |
a |
b |
b |
a |
b |
-функция |
0 |
0 |
0 |
1 |
2 |
Состояние |
1 |
2 |
3 |
4 |
5 |
6 |
Переходы по a |
2 |
2 |
2 |
5 |
2 |
2 |
Переходы по b |
1 |
3 |
4 |
1 |
6 |
4 |
Префикс-функция, построение автомата поиска подстрок с ее использованием (см. вики-конспекты)
Префикс-функция (англ. prefix-function) от строки — массив длин наибольших бордеров для каждой позиции этой строки |
Здесь и далее считаем, что символы в строках нумеруются с .
Определим
префикс-функцию от строки
в
позиции
следующим
образом:
.
Если мы не нашли такого
,
то
Наивный алгоритм вычисляет префикс-функцию непосредственно по определению, сравнивая префиксы и суффиксы строк. Обозначим длину строки за . Будем считать, что префикс-функция хранится в массиве .
[Править]Псевдокод
int[] prefixFunction(string s):
int[] p = int[s.length]
fill(p, 0)
for i = 1 to n
for k = 1 to i
if s[1..k] == s[i - k + 1..i]
p[i] = k
return p
[Править]Пример
Рассмотрим
строку
,
для которой значение префикс-функции
равно
.
Шаг |
Строка |
Значение функции |
|
a |
0 |
|
ab |
0 |
|
abc |
0 |
|
abca |
1 |
|
abcab |
2 |
|
abcabc |
3 |
|
abcabcd |
0 |
[Править]Время работы
Всего
итераций
цикла, на каждой из который происходит
сравнение строк за
,
что дает в итоге
.
[Править]Эффективный алгоритм
Вносятся несколько важных замечаний:
Заметим, что
.
Чтобы показать это, рассмотрим
суффикс,оканчивающийся на позиции
и
имеющий длину
,
удалив из него последний символ, мы
получим суффикс, оканчивающийся на
позиции
и
имеющий длину
,
следовательно неравенство
неверно.Избавимся от явных сравнений строк. Пусть мы вычислили
,
тогда, если
,
то
.
Если окажется, что
,
то нужно попытаться попробовать
подстроку меньшей длины. Хотелось бы
сразу перейти к такому бордеру наибольшей
длины, для этого подберем такое
,
что
.
Делаем это следующим образом. За
исходное
необходимо
взять
,
что следует из первого пункта. В случае,
когда символы
и
не
совпадают,
—
следующее потенциальное наибольшее
значение
,
что видно из рисунка. Последнее
утверждение верно, пока
,
что позволит всегда найти его следующее
значение. Если
,
то
при
,
иначе
.
[Править]Псевдокод
int[] prefixFunction(string s):
p[1] = 0
for i = 2 to n
k = p[i - 1]
while k > 0 and s[i] != s[k + 1]
k = p[k]
if s[i] == s[k + 1]
k++
p[i] = k
return p
