Часто сложение строк называют конкатенацией, и рассматривают как бинарную математическую операцию.
Эта операция (далее ) обладает интересными свойствами.
Конкатенация логично распространяется так же и на структуры данных, являющиеся последовательностями, такие, как списки, массивы.
Их также можно отнести к моноидам.
Trie - структура, которая (довольно неожиданно) уже встречалась нам в контексте сортировки послеовательнсотей за линейное врем. Она использовалась в одной из модификаций Radix Sort - это довольно экзотическое применение trie.
кстати, одно из названий trie - radix trie
Само название trie получилось "урезанием" слова retrieval и намекает на то, для чего используется структура.
Зачастую trie используют как ассоциативный массив для хранения информации
Если посмотреть на листья, в trie компактно упакованы следующие строки:
А если добавить узлы, не являющиеся листьями -
За , где - глубина trie, можно получить информацию о том, содержится ли в нем строка, или нет.
К сожалению, иногда trie может "съесть" много памяти, если получилось так, что под каждый символ каждой хранимой последовательности память выделяется отдельно
Trie - рекурсивная структура данных. И ее определение рекурсивно:
struct Trie {
value, -- значение любого типа для хранения в узле
children: Mapping of type (char : pointer to Trie) -- ассоциативный массив с указателями на другие trie
}
Поскольку trie - ассоциативный массив, он должен поддердживать:
Insert(key, value)Delete(key)Search(key)Trie во многом похоже на деревья, операцию обхода TraverseМожно ли сделать так, чтобы множество trie'в стало
Рассмотрим следующую ситуацию: trie испольуют, например, для задачи сохранения всех возможных суффиксов строки.
Строка: "AAABAAAB"
Вот что мы получим после сжатия Внимание! Сжаты не все возможные узлы, у только набор самых "вопиющих", находящийся слева.
Еще один пример
Внимание, ошибка! На самом деле нет узла "упила", а еслть узел "пила", выходящий из узла "у".
</font>
Автоматы можно сложить!
Серые линии - "пропавшие" суффиксы. Они не нужны, так как мы выбираем наибольший из присутствующих в атомате, то есть в trie, суффиксов.
Автомат может обрабатывать следующие строки: AGAG, GTAG
Промежуточный итог:
Чтобы расчитать суффиксные ссылки, для каждого узла в trie составляется набор суффиксов. Если суффикс присутсвует в trie, до от узла до этого суффикса проставляется ссылка.
Зеленые стрелки указывают на словарные суффиксы. То есть на те суффиксы, которые сами являются целевыми словами.
Обратите внимание на зеленую стрелку, крайнюю слева внизу (выделена пунктиром). Непосредственно два узла A и A суффиксными ссылками не соединены, но соединены через узел A в правом ряду суффиксными ссылками (так же выделены).
Правила постоения "словарно-суффиксных" ссылок просты: если по суффиксным ссылкам можно дойти от текущего узла до узла, который так же является и словарным суффиксом, то между началом и концом пути проставляется словарная ссылка.
Итак, автомат на изображении выше ищет следующие строки: A, G, CG, CG, CGA, GAA. Если в тексте встречается любая из них, автомат должен сообщить об этом. Если строки встречаются "одновременно", например, после символа C идет G - автомат должен сообщить о двух найденных строках, CG и G.
Разберем поиск в строке CACGAA
Узел Остаток Результат ---------------------------- () - CACGAA - None (C) - ACGAA - None (A) - CGAA - A (C) - GAA - None (CG) - AA - CG, G (CGA) - A - CGA, A (GAA) - ε - GAA
Обход trie в алгоритме Ахо-Корасик:
- На каждом шаге из текущего ущла переходить в следующий, если у него есть ребенок. Если ребенка нет, то переходить в суффикс и искать его детей. Если у суффикса у детей нет, то переходить в суффикс суффикса и т.д... рекурсивно до корня.
</font>
Основное задание (Сделано любое задание из двух - 2 балла, два из двух - 3 балла):
</font>