Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Структуры данных.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1.58 Mб
Скачать

[Править]Решение

Для решения этой задачи заменим исходную сеть   на   следующим образом. Сначала добавим в граф вершины   — исток и   — сток. Для каждого ребра   добавим ребра   и  , а также сделаем в ребре   изменения:   (см. рисунок 2).

Рисунок 2. Слева - изначальный граф. Для каждого ребра заданы его нижняя и верхняя пропускные способности. Справа - граф после преобразований ребер.

Каждое ребро изначального графа заменяется на три новых. Если по ребру   в исходной сети протекает поток  , то в новой сети по ребру  должен течь поток, равный  , то есть его пропускной способности. Поток, который вытекает из   по ребру в  , заменяется на поток, который протекает по ребрам   и   (поскольку сумма их пропускных способностей в полученном графе равна  ). Аналогично, для вершины   суммарный входящий поток не изменился. Таким образом, любой допустимый поток по любому ребру в изначальном графе можно распределить между тремя ребрами в полученном графе. Заметим, что в сети   все  , то есть мы имеем обыкновенную сеть.

Требовалось найти циркуляцию в исходной сети, а значит проверить существование потока, для которого выполнено равенство   для всех вершин графа. Это равносильно существованию потока между вершинами   и   в сети  , который полностью насытит ребра, исходящие из истока. Действительно, этот поток в исходном графе насытит  -ое ребро как минимум на  , что и является необходимым требованием. Если этот поток существует, то будет выполнено:

  •  где  , то есть для всех исходных вершин;

  • В  , что удовлетворяет всем ограничениям.

Значит, этот поток и есть циркуляция.

Запустим в новой сети один из алгоритмов поиска максимального потока. Если он не смог полностью насытить все ребра их истока, то и никакой другой по величине поток этого сделать не сможет, значит, циркуляции нет. Для получения величин потоков вдоль каждого ребра в изначальной сети достаточно прибавить к потокам вдоль ребер в сети  соответствующие значения минимальной пропускной способности.

[Править]Псевдокод

G // пустой граф, вершины 0 и n + 1 - исток и сток

n, m; // вершин, ребер в исходном графе

edge // ребро с полями (from, to, min_cap, cap)

Для i = 1 to m

считать ребро edge

добавить в граф G ребро (0, edge.to, 0, edge.min_cap)

добавить в граф G ребро (edge.from, edge.to, 0, edge.cap - edge.min_cap)

добавить в граф G ребро (edge.from, n + 1, 0, edge.min_cap)

max_flow = наибольший поток в графе G

Для всех ребер, инцидентных истоку

если для текущего ребра flow < cap

циркуляции НЕТ

  1. Поиск подстрок

Сравнение — «чёрный ящик»

Во всех алгоритмах этого типа сравнение является «чёрным ящиком» для программиста.

Преимущества:

  • позволяет использовать стандартные функции сравнения участков памяти (man *cmp(3)), которые, зачастую, оптимизированы под конкретное железо.

Недостатки:

  • не выдается точка, в которой произошло несовпадение.

[править]По порядку сравнения паттерна в тексте

[править]Прямой

Преимущества:

  • отсутствие регрессии на «плохих» данных.

Недостатки:

  • не самая хорошая средняя асимптотическая сложность.

[править]Обратный

Паттерн движется по тексту слева направо, но сравнение подстрок происходит справа налево.

Преимущества:

  • при несовпадении позволяет перемещать паттерн по строке сразу на несколько символов.

Недостатки:

  • производительность сильно зависит от данных.

[править]Сравнение в необычном порядке

Специфические алгоритмы, основанные, как правило, на некоторых эмпирических наблюдениях над словарём.[1]

[править]По количеству поисковых шаблонов

Сколько поисковых шаблонов может обработать алгоритм за один раз.

  • один шаблон (англ. single pattern algorithms)

  • конечное количество шаблонов (англ. finite set of patterns)

  • бесконечное количество шаблонов (англ. infinite number of patterns) (см. Теория формальных языков)

[править]По необходимости препроцессинга текста

Виды препроцессинга:

  • Префикс-функция

  • Z-функция

  • Бор

  • Суффиксный массив

Алгоритмы, использующие препроцессинг — одни из самых быстрых в этом классе.

[править]Сравнение алгоритмов

  • ­ — размер алфавита

  •  — длина текста

  •  — длина паттерна

  •  — размер ответа(кол-во пар)

  •  — суммарная длина всех паттернов

Название

Среднее

Худшее

Препроцессинг

Дополнительная память

Кол-во поисковых шаблонов

Порядок сравнения

Описание

Наивный алгоритм  (Brute Force algorithm)

Single

Прямой

Сравнение — «чёрный ящик». Если  достаточно мало по сравнению с  , то асимптотика будет близкой к  , что позволяет использовать его на практике в случаях, когда паттерн много меньше текста (например, ctrl+F в браузерах)

Поиск подстроки в строке с помощью Z-функции

Single

Прямой

Алгоритм Рабина-Карпа  (Karp-Rabin algorithm)

Single / Finite

Прямой

Данный алгоритм использует хэширование, что снижает скорость в среднем. Можно модифицировать для поиска нескольких паттернов

Алгоритм Кнута-Морриса-Пратта  (Knuth-Morris-Pratt algorith)

Single

Прямой

Использует префикс-функцию

Алгоритм Колусси  (Colussi algorithm)

Single

Прямой / Обратный

Оптимизация Алгоритма Кнута-Морриса-Пратта использует как прямой, так и обратный обход

Алгоритм Ахо-Корасик  (Aho–Corasick string matching algorithm)

Finite

Прямой

Строит конечный автомат. Можно хранить таблицу переходов как индексный массив (array), а можно как Красно-черное дерево. В последнем случае уменьшится расход памяти, но ухудшится асимптотика

Алгоритм Shift-Or

   — размер машинного слова

Single

Прямой

Использует тот факт, что в современных процессорах битовые сдвиг и или являются атомарными. Эффективен, если  . Иначе деградирует и по памяти, и по сложности

Алгоритм Бойера-Мура  (Boyer-Moore algorithm)

Single

Обратный

Считается наиболее быстрым из алгоритмов общего назначения. Использует эвристики. Существует большое количество оптимизаций[2]

Поиск подстроки в строке с помощью суффиксного массива (Suffix array)

Single

Прямой

Использует Суффиксный массив. Если использовать Largest common prefix (lcp), то можно уменьшить асимптотику до  . Суффиксный массив можно строить стандартными способами илиалгоритмом Каркайнена-Сандерса. Асимптотика приведена для построения суффиксного массива с помощью алгоритма Каркайнена-Сандерса

Поиск подстроки в строке с помощью суффиксного дерева  (Suffix tree)

Single

Прямой

Позволяет выполнять поиск подстроки в строке за линейное время

    Допустимые/недопустимые сдвиги

Большинство текстовых редакторов умеет искать заданное слово в редактируемом тексте — хочется, чтобы это происходило быстро. Говоря формально, задача поиска подстрок (string-matching problem) состоит в следующем. Пусть даны «текст» — массив T[1..n] длины n и «образец» — массив P[1..m] длины m<n. Мы считаем, что элементы массивов P и T — символы некоторого конечного алфавита (например, X = {0, 1} или X = {а, b, ..., z}). Массивы, состоящие из символов алфавита X, называют строками (strings) символов, или словами в этом алфавите.

Будем говорить, что образец Р входит со сдвигом s, или, эквивалентно, входит с позиции s + 1 в текст Т, если 0≤ s п — m и T[s+1, ... s + m] =P[1...m] (иными словами, если T[s+j] =P[j] при 1 ≤ j m). Если Р входит со сдвигом s в текст Т, то говорят, что s — допустимый сдвиг, в противном случае s  недопустимый сдвиг. Задача поиска подстрок состоит в нахождении всех допустимых сдвигов для данных текста T и образца Р 

Пусть требуется найти все вхождения образца P='abaa' в текст T='аbсаbааbс'. Образец входит в текст только один раз, со сдвигом s=3 (стало быть, 3 — допустимый сдвиг).

Первый приходящий в голову алгоритм для поиска образца P в тексте Т последовательно проверяет равенство T[s+1, ... s + m] =P [1...m] для каждого из п — т + 1 возможных значений s.

Можно сказать, что мы двигаем образец вдоль текста и проверяем все его положения . Простейший алгоритм ищет образец P='aab' в тексте Т='acaabc'. Изображены четыре последовательные попытки. Буквы, для которых сравнение прошло успешно, соединены прямыми. Буквы, на которых выявлено несовпадение, соединены ломаными линиями. При этом s=2 -  единственный допустимый сдвиг.

Простейший алгоритм — не лучший. Неэффективность простейшего алгоритма связана с тем, что информация о тексте Т, получаемая при проверке данного сдвига s, никак не используется при проверке последующих сдвигов. Между тем такая информация может очень помочь. Пусть, например, P  'aaab', и мы выяснили, что сдвиг s=0 допустим. Тогда сдвиги 1, 2 и 3 заведомо недопустимы, поскольку T[4] =b.

    Конкатенация строк, префикс строки, суффикс строки

В строке важен порядок символов, так, строки 01 и 10 различны. Длина строки равна числу символов в строке. Длина пустой строки равна нулю, длина строки 1 равна единице, длина строки 1001 четырем. Если X и Y строки, то их сцеплением или конкатенацией называется строка XY, полученная приписыванием символов строки Y за символами строки X.

В языке Turbo Pascal определен стандартный тип данных string. Значения этого типа – последовательность символов длиной от 0 до 255. При определении типа строки можно указать в квадратный скобках максимальный размер строки. Если размер строки не указан, то он считается равным 255.

Изображением строки называется последовательность символов, заключенная в апострофы. Значение для строковой переменной можно прочесть из стандартного файла ввода и поместить в стандартный файл вывода.

Операция + используется для конкатенации строк, в этом случае к первой строке приписывается вторая.

К строкам применимы операции отношения. Сравнение осуществляется слева направо в соответствии с кодами символов. При сравнении строк разной длины принято соглашение, что отсутствующий символ меньше любого кода символа строки, поэтому верно ‘дом’ < ‘дома’.

Символы в строке перенумерованы, начиная с 1. Количество символов в строке или длину строки можно определить с помощью стандартной функции length(s). Получить доступ к символу строки можно по его индексу, для этого за строковой переменной в квадратных скобках указывается индекс. Значение строковой переменной изменится, если изменится значение хотя бы одного из символов строки.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]