- •Граф. Ориентированный граф. Представления графа. Обход графа в глубину и в ширину.
- •Топологическая сортировка. Подсчет числа путей в орграфе.
- •Сильно связные компоненты.
- •Поиск кратчайших путей в графе. Алгоритм Флойда. Алгоритм Дейкстры. Алгоритм Форда-Беллмана.
- •Алгоритм a*. Эвристики.
- •Минимальное остовное дерево. Алгоритм Прима. Биномиальная куча.
- •Амортизационная стоимость. Фибоначчиева куча. Амортизационная стоимость (анализ)
- •Метод потенциалов
- •Фибоначчиева Куча
- •Структура
- •Время работы
- •Система непересекающихся множеств. Алгоритм Крускала.
- •Наивная реализация
- •Эвристика сжатия пути
- •Эвристика объединения по рангу
- •Потоки, Форда-Фалкерсона.
- •Декартово дерево
- •Дерево Фенвика. Дерево отрезков и динамическое программирование для rmq.
- •Сведение rmq к lca и наоборот.
- •Препроцессинг
- •Ответы на запросы
- •Алгоритм
- •Доказательство
- •Сложность
- •Алгоритм
- •Минимум внутри блока
- •Результат
- •Поиск нескольких минимумов на отрезке. Задача поиска подстрок. Алгоритм Рабина-Карпа. Конечный автомат. Алгоритм Бойера-Мура.
- •Метод хеширования
- •Алгоритм
- •Время работы
- •Алгоритм Бойера-Мура
- •Поиск со звездочками. Алгоритм Кнута-Морриса-Пратта.
- •Время работы
- •Алгоритм Ахо-Корасика.
- •Дерево ключевых слов (бор)
- •Пример дерева ключевых слов (бора)
- •Построение бора
- •Поиск строки в бору
- •Автомат Ахо-Корасик
- •Суффиксное дерево, Алгоритм Укконена.
- •2. Квадратичный алгоритм
- •3. Линейный алгоритм
- •Суффиксный массив.
- •Наивный алгоритм поиска
- •Алгоритм, использующий префиксы циклических сдвигов
- •Исключения
- •Шаблоны
- •Stl: итераторы
- •Сортировка и поиск в stl. Алгоритмы stl
- •Куча в stl. Алгоритмы stl.
- •Ассоциативный массив. Интерфейс, варианты реализации.
Суффиксный массив.
Cуффиксным
массивом строки
называется
массив
целых
чисел от
до
,
такой, что суффикс
—
-й
в лексикографическом порядке среди
всех непустых суффиксов строки
.
Пример:
.
Суффиксы
в
лексикографическом
порядке:
1)
2)
3)
4)
5)
6)
7)
Значит,
суффиксный массив для строки
равен
.
Применения:
Позволяет
найти все вхождения образца
в
строку
за
время
Позволяет
вычислить
(longest
common prefix) для всех соседних в лексикографическом
порядке суффиксов строки
за
,
то есть построить массив
,
где
—
длина наибольшего
общего префикса суффиксов
и
.
Наивный алгоритм поиска
Простейший способ узнать, встречается ли образец в тексте, используя суффиксный массив, — взять первый символ образца и бинарным поиском по суффиксному массиву найти диапазон с суффиксами, начинающимися на такую же букву. Так как все элементы в полученном диапазоне отсортированы, а первые символы одинаковые, то оставшиеся после отбрасывания первого символа суффиксы тоже отсортированы. А значит, можно повторять процедуру сужения диапазона поиска уже по второму, затем третьему и так далее символу образца до получения либо пустого диапазона, либо успешного нахождения всех символов образца.
Бинарный
поиск работает за время равное
,
а сравнение суффикса с образцом не может
превышать длины образца.
Таким
образом время работы алгоритмы
,
где
—
текст,
—
образец.
Алгоритм, использующий префиксы циклических сдвигов
От
этого алгоритма несложно перейти к
алгоритму за
.
Итак, основная идея: на каждом шаге будем
сортировать префиксы циклических
сдвигов длины
.
Еще одно важное дополнение: после каждой
фазы каждому префиксу циклического
сдвига
будет
присваиваться номер класса
эквивалентности
среди
этих префиксов. Причем классы
эквивалентности должны быть пронумерованы
в лексикографическом порядке
соответствующих представителей.
Сначала легко можно отсортировать за префиксы длины , то есть символы. А номера классов поставить в соответствии с порядковым номером символа в алфавите.
Рассмотрим
теперь переход от префиксов длины
к
префиксам длины
.
Научимся сравнивать два префикса
длины
за
:
Пусть даны префиксы
,
,
сравним сначала их левые половинки,
использовав значения
с
предыдущего шага, если
,
то префиксы соотносятся так как же,
как
и
,
если
,
то переходим к сравнению
и
.
Итак, отсортировать префиксы длины
можно
за
.
Вычислить новые
можно
просто пробежавшись в лексикографическом
порядке по префиксам, и увеличивая номер
соответствующего класса на
,
если текущий префикс не совпадает с
предыдущим (сравнивать с помощью
старых
).
После
шага
все
циклические сдвиги будут отсортированы.
Всего шагов
,
каждый шаг проводится за
,
итоговая асимптотика
.
ООП. Основные понятия ООП. Конструкторы/деструкторы. Перегрузка методов. Сокрытие методов. Какие методы и операторы необходимы для использования типа в качестве параметра стандартного шаблонного контейнера? Ключевые слова virtual и const. Что такое срезка? Множественное наследование.
Что такое класс?
Класс в программировании — разновидность абстрактного типа данных в объектно-ориентированном программировании (ООП), характеризуемый способом своего построения.
Это составной тип данных: каждый объект такого типа может содержать в себе несколько полей. Также в классе могут быть определены методы, позволяющие работать с объектами класса.
Чем класс в С++ отличается от структуры?
В структуре по умолчанию все поля и метода – публичные.
В классе – приватные.
В этом заключается основное отличие структуры и класса.
Также не принято использование методов в структурах.
В чем отличие класса от объекта?
Объект — некоторая сущность в виртуальном пространстве, обладающая определённым состоянием и поведением, имеет заданные значения свойств (атрибутов) и операций над ними (методов). Ключевое понятие парадигмы ООП.
В объектно-ориентированной программе с применением классов каждый объект является «экземпляром» некоторого конкретного класса, и других объектов не предусмотрено.
Структура лежит в памяти непрерывным блоком, а класс – не обязательно (из-за наследования)
Основные понятия ООП
Public – доступ открыт всем, кто видит определение данного класса.
Private – доступ открыт самому классу (т.е. функциям-членам данного класса) и друзьям (friend) данного класса, как функциям, так и классам.
Protected – доступ открыт классам, производным от данного.
ООП – основные понятия объект и класс
Инкапсуля́ция — свойство языка программирования, позволяющее пользователю не задумываться о том, что находится внутри программного компонента, а взаимодействовать с ним посредством предоставляемого интерфейса (методов), а также объединить и защитить жизненно важные для компонента данные.
При этом пользователю предоставляется только интерфейс — спецификация объекта.
Другими словами, инкапсуляция – сокрытие деталей реализации.
Полиморфи́зм — возможность объектов с одинаковой спецификацией иметь различную реализацию.
В объектно-ориентированных языках класс является абстрактным типом данных. Полиморфизм реализуется с помощью наследования классов и виртуальных функций. Класс-потомок наследует сигнатуры методов родителя, а реализация, в результате переопределения метода, этих методов может быть другой, соответствующей специфике класса-потомка.
Насле́дование — механизм объектно-ориентированного программирования, позволяющий описать новый класс на основе уже существующего (родительского), при этом свойства и функциональность родительского класса заимствуются новым классом.
Чисто виртуальные методы — это методы, которые в определении класса явным образом не определены. Делая метод чисто виртуальным, вы сообщаете компилятору о том, что в текущем классе определения для данного метода не существует. О классе, в котором объявлен хотя бы один чисто виртуальный метод, говорят, что он абстрактный, поскольку реализовать его невозможно. Компилятор гарантирует, что, если класс содержит один или несколько чисто виртуальных методов, он никогда не будет использован для построения объекта.
Конструкторы/деструкторы
Конструктор класса в объектно-ориентированном программировании — специальный блок инструкций, вызываемый при создании объекта.
Деструктор класса в объектно-ориентированном программировании — специальный блок инструкций, вызываемый при уничтожении объекта.
Пример:
Class A {
public:
A(); //конструктор по умолчанию
A(int b, char c);
~A(); //деструктор
}
Перегрузка методов.
Класс может содержать несколько конструкторов (и все они имеют одинаковые имена). Эти конструкторы отличаются только количеством или типом параметров.
В С++ аналогично можно поступить с любым методом или функцией. В частности, можно перегрузить метод, используя его имя для нескольких методов, отличающихся друг от друга количеством или типом параметров.
При вызове перегруженного метода компилятор определит нужную версию на основе переданного ему параметра.
С++ не позволяет перегружать метод только на основе возвращаемого им типа, поскольку во многих случаях компилятор не сможет определить, какую версию метода ему необходимо вызвать. Например, если значение, возвращаемое методом, нигде не перехватывается, компилятор не сможет "понять", к какой версии метода вы обратились.
Метод можно перегрузить на основе спецификатора const. Можно написать два метода с одним именем и одинаковыми параметрами, но один из них объявить const-методом.
Сокрытие методов
Метод можно объявить в private. Тогда доступ к нему будут иметь только метода этого класса. Доступ открыт самому классу (т.е. функциям-членам данного класса) и друзьям (friend) данного класса, как функциям, так и классам.
Перегрузка стандартных операторов. Способы перегрузки операторов.
Для выполнения операций с объектами класса необходимо перегрузить для них операторы, соответствующие этим операциям.
Нельзя переопределить операторы « ?: », « & », « . », « , », « -> »
Также нельзя переопределить приоритеты операторов.
1 способ. В виде метода класса
class A { … bool operator<(const A& rsh) {…} … }
2 способ. Внешне
bool operator<(const A& lsh, const A& rsh) {…}
Перегрузка оператора ++
Префиксная:
A& operator++() {
increment();
return(*this);
}
Постфиксная:
const A operator++(int) {
A temp=*this;
increment;
return temp;
}
Какие методы и операторы необходимы для использования типа в качстве параметра стандартного шаблонного контейнера?
Ключевые слова virtual и const
В теме переопределения методов есть одна маленькая деталь, связанная с ис-пользованием ключевого слова virtual. Подклассами могут переопределяться все методы суперкласса, но vitual метод надо делать, чтобы суперкласс знал, что наследники могут переопределить этот метод. Ключевое слово virtual размещается в начале объявления метода.
Чтобы переопределить метод, достаточно снова объявить его в определении подкласса точно так, как он был объявлен в суперклассе. Новое определение этого метода необходимо разместить в файле реализации подкласса.
#include <iostream>
class A {
public:
int virtual get() {return 1;}
};
class B: public A{
public:
int get() {return 2;}
};
int main(){
B b;
A* a=&b;
Map<int, int> s;
std::cout<<a->get();
system("pause");
return 0;
}
Выведет 2; если уберем virtual, то выведет 1
Ключевое слово const применяется для:
Создания констант
Защиты переменных (Такое преобразование обеспечивает определенную степень защиты переменных от изменения их значений со стороны других частей программного приложения.)
Использование const-ссылок (Передавая функции ссылку, вы одним "выстрелом" убиваете сразу двух "зайцев": и копия не создается, и исходная переменная не будет подвергнута никаким случайным изменениям.)
Если ставим const перед « { » при перегрузке оператора, то это означает, что оператор будет работать только с константными объектами данного класса.
Что такое срезка?
Подклассы сохраняют свои переопределенные методы при обращении к ним посредством указателей или ссылок "суперклассового" типа. Но они теряют свою уникальность при приведении объекта к типу суперкласса.
Потеря переопределенных методов и данных подкласса называется расслоением.
A – родитель, B – ребенок. A a=b. Тогда методы b не работают. Если A &a=b, то работают
Множественное наследование
Определить класс с несколькими родителями синтаксически очень легко. Для этого достаточно при объявлении имени класса перечислить все его суперклассы.
class Baz: public Foo, public Bar {
…
};
После перечисления нескольких родителей объект класса Bar будет обладать следующими характеристиками:
Объект класса Baz станет поддерживать public-методы и включать открытые члены данных обоих классов Foo и Bar.
Методы класса Baz будут иметь доступ к защищенным (protected) данным и методам обоих классов Foo и Bar.
Объект класса Baz можно привести либо к типу Foo, либо к типу Bar.
При создании нового объекта класса Baz будут автоматически вызваны конструкторы по умолчанию классов Foo и Bar, причем в порядке, в котором эти имена были перечислены в определении класса Baz.
При удалении объекта класса Baz будут автоматически вызваны деструкторы классов Foo и Bar, причем в порядке, обратном тому, в котором эти имена были перечислены в определении класса Baz.
