- •Алгоритмы и алгоритмические языки
- •Лекция 1
- •Представление чисел в эвм
- •Вещественные
- •Ошибки вычислений
- •Лекция 2
- •Алгоритмы. Сведение алгоритмов.
- •Нижние и верхние оценки.
- •Сортировки
- •Постановка задачи
- •Сортировка пузырьком.
- •Сортировка слиянием с рекурсией.
- •Сортировка слиянием без рекурсии.
- •Лекция 3
- •Алгоритмы. Сведение алгоритмов.
- •Сортировки и связанные с ними задачи.
- •Доказательство корректности работы алгоритма.
- •Оценки времени работы алгоритма.
- •Некоторые задачи, сводящиеся к сортировке.
- •Лекция 4
- •Алгоритмы. Сведение алгоритмов.
- •Сортировки и связанные с ними задачи.
- •HeapSort или сортировка с помощью пирамиды.
- •Алгоритмы сортировки за время o(n)
- •Сортировка подсчетом
- •Цифровая сортировка
- •Сортировка вычерпыванием
- •Лекция 5
- •Алгоритмы. Сведение алгоритмов.
- •Порядковые статистики.
- •Поиск порядковой статистики за время (n) в среднем
- •Поиск порядковой статистики за время (n) в худшем случае
- •Язык программирования c.
- •Переменные
- •Структуры данных.
- •Вектор.
- •Лекция 6
- •Стек. Реализация 1 (на основе массива).
- •Стек. Реализация 2 (на основе массива с использованием общей структуры).
- •Стек. Реализация 3 (на основе указателей).
- •Стек. Реализация 4 (на основе массива из двух указателей).
- •Стек. Реализация 5 (на основе указателя на указатель).
- •Очередь.
- •Стандартная ссылочная реализация списков
- •Ссылочная реализация списков с фиктивным элементом
- •Реализация l2-списка на основе двух стеков
- •Реализация l2-списка с обеспечением выделения/освобождения памяти
- •Лекция 7
- •Структуры данных. Графы.
- •Поиск пути в графе с наименьшим количеством промежуточных вершин
- •Представление графа в памяти эвм
- •Массив ребер
- •Матрица смежности
- •Матрица инцидентности
- •Списки смежных вершин
- •Реберный список с двойными связями (рсдс) (для плоской укладки планарных графов)
- •Лекция 8
- •Структуры данных. Графы.
- •Поиск кратчайшего пути в графе
- •Алгоритм Дейкстры
- •Конец вечного цикла
- •Алгоритм Дейкстры модифицированный
- •Конец вечного цикла
- •Лекция 9
- •Бинарные деревья поиска
- •Поиск элемента в дереве
- •Добавление элемента в дерево
- •Поиск минимального и максимального элемента в дереве
- •Удаление элемента из дерева
- •Поиск следующего/предыдущего элемента в дереве
- •Слияние двух деревьев
- •Разбиение дерева по разбивающему элементу
- •Сбалансированные и идеально сбалансированные бинарные деревья поиска
- •Операции с идеально сбалансированным деревом
- •Операции со сбалансированным деревом
- •Поиск элемента в дереве
- •Добавление элемента в дерево
- •Удаление элемента из дерева
- •Поиск минимального и максимального элемента в дереве
- •Поиск следующего/предыдущего элемента в дереве
- •Слияние двух деревьев
- •Разбиение дерева по разбивающему элементу
- •Лекция 10
- •Красно-черные деревья
- •Отступление на тему языка с. Поля структур.
- •Отступление на тему языка с. Бинарные операции.
- •Высота красно-черного дерева
- •Добавление элемента в красно-черное дерево
- •Однопроходное добавление элемента в красно-черное дерево
- •Удаление элемента из красно-черного дерева
- •Лекция 11
- •Высота b-дерева
- •Поиск вершины в b-дереве
- •Отступление на тему языка с. Быстрый поиск и сортировка в языке с
- •Добавление вершины в b-дерево
- •Удаление вершины из b-дерева
- •Лекция 12
- •Хеширование
- •Метод многих списков
- •Метод линейных проб
- •Метод цепочек
- •Лекция 14
- •Поиск строк
- •Отступление на тему языка с. Ввод-вывод строк из файла
- •Алгоритм поиска подстроки с использованием хеш-функции (Алгоритм Рабина-Карпа)
- •Конечные автоматы
- •Отступление на тему языка с. Работа со строками
- •Алгоритм поиска подстроки, основанный на конечных автоматах
- •Лекция 15
- •Алгоритм поиска подстроки Кнута-Морриса-Пратта (на основе префикс-функции)
- •Алгоритм поиска подстроки Бойера-Мура (на основе стоп-символов/безопасных суффиксов)
- •Эвристика стоп-символа
- •Эвристика безопасного суффикса
- •Форматы bmp и rle
- •Bmp без сжатия.
-
Эвристика безопасного суффикса
Рассмотрим несколько примеров.
Пример 1. S=”abababbaab”, W=”abbaab”.
Сначала сравниваем суффикс S6 и W. Как уже отмечалось, сравнение производим справа налево. Выясняется, что максимальный совпадающий суффикс S6 и W ”ab” состоит из двух символов. Ближайшее справа вхождение подстроки ”ab” в строку W начинается с позиции 0, поэтому далее можно сравнивать с W уже S6+strlen(W)-strlen(”ab”)+0=S10, т.к. при таком сдвиге впервые та же самая подстрока ”ab” строки S совпадет с соответствующей подстрокой W.
Иными словами, в этом примере мы искали максимальное i<6, такое что ”ab” являлась суффиксом Wi. Следующий претендент на сравнение вычислялся по формуле S6+strlen(W)-i.
Пример 2. S=”abababbaab”, W=”bbbaab”.
Сначала, как и в предыдущем примере, сравниваем суффикс S6 и W. Как уже отмечалось, сравнение производим справа налево. Выясняется, что максимальный совпадающий суффикс S6 и W ”ab” состоит из двух символов. Подстрока ”ab” больше в строку W не входит. Однако максимальное начало строки W, совпадающее с соответствующим суффиксом ”ab”, имеет длину 1, поэтому далее можно сравнивать с W уже S6+strlen(W)-strlen(”ab”)+1=S11. Действительно, при таком сдвиге впервые часть той же самой подстрока ”ab” строки S (имеется в виду подстрока ”b”) совпадет с соответствующей подстрокой W.
Иными словами, в этом примере мы искали максимальное i2, такое что Wi являлась бы суффиксом ”ab”. Следующий претендент на сравнение вычислялся по формуле S6+strlen(W)-i (сравнить с предыдущим примером).
Введем обозначение. Будем говорить, что строки A и B сравнимы: A B, если A является суффиксом B или B является суффиксом A.
Обобщая приведенные примеры, мы можем сказать, что мы искали максимальное i<strlen(W), такое что Wi ”ab”.
Введем функцию , такую что (l) равна максимальному i<strlen(W), такому, что Wi сравнима с суффиксом W длины l. Если такого не нашлось, то (l)=0.
Пусть сравнивается суффикс Sk и W. Пусть C - максимальный по длине общий суффикс Sk и W. Следующим претендентом на сравнение будет
Sk+ strlen(W) - (strlen(C)) .
Осталось выяснить – каким образом задать функцию (l).
По определению (l)=Max{i<strlen(W): Wi Suff(W,l)}, где Suff(W,l) – суффикс W длины l. То же самое можно переписать иначе:
(l) = Max{ Max{i<strlen(W): Wi – суффикс Suff(W,l)},
Max{i<strlen(W): Suff(W,l) – суффикс Wi } }
Выше мы ввели функцию p(i), равную максимальной длине суффикса строки Wi, являющегося префиксом W. По определению имеем, что Wp(strlen(W)) является суффиксом W, поэтому Wp(strlen(W)) Suff(W,l). Из последнего вытекает, что
(l) p(strlen(W))
Т.о. получаем
(l) = Max{ Max{i<strlen(W): Wi – суффикс Suff(W,l)},
Max{i<strlen(W): Suff(W,l) – суффикс Wi } }
Более того, Max{i<strlen(W): Wi – суффикс Suff(W,l)} не может превзойти Wp(strlen(W)), т.к. если бы это произошло, то мы получили бы суффикс Suff(W,l) (а следовательно и суффикс W), являющийся префиксом W, длиной больше максимально возможной длины суффикса W, являющегося префиксом W. Т.о. получаем
(l) = Max{ p(strlen(W)), Max{ p(strlen(W))i<strlen(W): Suff(W,l) – суффикс Wi } }
Легко увидеть, что поиск
(l)=Max{ p(strlen(W))i<strlen(W): Suff(W,l) – суффикс Wi }
сводится к поиску самого правого участка строки W, совпадающего с Suff(W,l) (естественно, рассматриваются участки левее самого Suff(W,l)).
Пример:
l=2; W=”abacabacab”;//выделен Suff(W,l) и его правое вхождение в W
Отметим, что такого участка может не существовать. Если рассмотреть строку W’, представляющую собой перевернутую строку W, то задачу можно свести к поиску самого левого вхождения строки W’l в строку W’ (правее начальной позиции):
(l)=Max{ p(strlen(W))i<strlen(W): Suff(W,l) – суффикс Wi }=
=strlen(W) - Min{ i>l: W’l – суффикс Wi }+l
Пример:
l=2; W’=”bacabacaba”;//выделен W’l и его левое вхождение в W
Рассмотрим начало строки W’, завершающееся найденным левым вхождением W’l в строку W (в примере это – ”bacaba”). Более формально: рассмотрим W’I, где I=argMin{ i>l: W’l – суффикс Wi }.
Легко увидеть: l=p’(I), где p’ – префикс-функция W’. Действительно, если бы нашелся больший суффикс W’I , являющийся одновременно префиксом W’ , то, соответственно, нашлось бы и более левое вхождение подстроки W’l в строку W (т.к. начало более длинного суффикса должно совпадать с W’l).
С другой стороны равенство l==p’(I) влечет за собой тот факт, что W’l является суффиксом W’I.
Т.о. имеем
Min{ i>l: W’l – суффикс Wi }= Min{ i>l: l==p’(i)}
Тогда получаем
(l)= strlen(W) +l - Min{ i>l: l==p’(i)}
Последнее равенство дает алгоритм вычисления (t): следует перебрать все значения i в порядке убывания и для каждого из них выполнить присвоение
[p’(i)]= strlen(W) + p’(i) – i если i>p’(i)
В конце концов, получаем
[l] = Max{ p(strlen(W)), [l]}
В двух последних формулах мы реализовали и как массивы.
В прилагаемой программе реализованы функции создания массивов m, p и . Реализованы функции поиска, использующие только эвристику стоп-символа, только эвристику безопасного суффикса и, наконец, функция поиска по обоим эвристикам.