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

Свойства суффиксных деревьев[править | править вики-текст]

Лемма. Местоположение w явно в компактном суффиксном дереве тогда и только тогда, когда w является не вложенным суффиксом t или w — правое ветвление.

Доказательство.  . Если   явно, то это может быть либо лист, либо вершина ветвления или корень (в этом случае   и w — вложенный суффиксt).

Если   — лист, тогда также является и суффиксом t. Значит, это должен быть не вложенный суффикс, так как иначе он появился бы где-нибудь ещё в строке t  v — суффикс t такой, что w — префикс v. Этот узел не может быть листом.

Если   — узел ветвления, тогда должны существовать, по меньшей мере, два выходящих ребра из   с различными метками. Это означает, что существуют два различных суффикса uv, что w — префикс u и w — префикс v, где v = wxsu = x  . Следовательно, w — правое ветвление.

. Если w является не вложенным суффиксом t, это должен быть лист. Если w — правое ветвление, то имеются два суффикса u и vu = wxsv =  ,x  , тогда w является узлом ветвления. Лемма доказана.

Теперь легко видеть, почему ответ на вопрос, входит ли слово w в строку t, может быть найден за время O(|w|): нужно только проверить, является ли wместоположением (явным или неявным) в cst(t).

Метки рёбер должны представлять собой указатели на положение в строке, чтобы суффиксное дерево расходовало память размером O(n). Метка (p, q) ребра означает подстроку   или пустую строку, если p > q.

Укконен вводит название открытые рёбра для рёбер, заканчивающихся в листьях. Пометки открытых рёбер записывают как (p,  ) вместо (p, |t|), где   — длина, всегда большая, чем |t|.

Пусть T —  -дерево. Пусть   — узел Tv — наидлиннейший суффикс w такой, что   — также узел T. Непомеченное ребро от   до   называетсясуффиксным звеном. Если v = w, оно называется атомарным.

Утверждение. В ast(t) и cst(t$), где $   t, все суффиксные звенья являются атомарными.

Доказательство. Символ $ называется символом-стражем. Первая часть (для ast(t)) следует из определения, так как местоположения являются явными. Для доказательства второй (случай cst(t)) части мы должны показать, что для каждого узла     также является узлом cst(t). Если   — узел cst(t), то является либо листом, либо узлом ветвления. Если является листом, тогда aw — не вложенный суффикс t. Благодаря символу-стражу, из леммы следует, что все суффиксы (включая корень, пустой суффикс) являются явными, так как только корень — вложенный суффикс. Поэтому w является листом или корнем. Если   — узел ветвления, тогда aw — правое ветвление, как и w. Следовательно, местоположение   явно по лемме. Утверждение доказано.

Как следует из этого доказательства, символ-страж гарантирует существование листьев для всех суффиксов. С таким символом не может быть вложенных суффиксов, кроме пустого. Если мы опустим символ-страж, некоторые суффиксы могут стать вложенными, и их местоположения станут неявными.

Требования суффиксного дерева к памяти[править | править вики-текст]

Утверждение. Компактное суффиксное дерево может быть представлено в виде, требующем O(n) памяти.

Доказательство. Суффиксное дерево содержит не более одного листа на каждый суффикс (в точности один с символом-стражем). Каждый внутренний узел должен быть узлом ветвления, следовательно, внутренний узел имеет по меньшей мере двух потомков. Каждое ветвление увеличивает число листьев по меньшей мере на единицу, поэтому мы имеем не более n внутренних узлов и не более n листьев.

Для представления строк, являющихся метками рёбер, мы используем индексацию в исходной строке, как описано выше. Каждый узел имеет не более одного предка и, таким образом, общее число ребер не превышает 2n.

Аналогично, каждый узел имеет не более одного суффиксного звена, тогда общее число суффиксных звеньев также ограничено числом 2nУтверждение доказано.

Как пример суффиксного дерева с 2n-1 вершинами можно рассмотреть дерево для слова  . Размер атомарного суффиксного дерева для строки tсоставляет O( ).

    Простейший алгоритм

Дан текст   и паттерн   такие, что   и элементы этих строк — символы из конечного алфавита  . Требуется проверить, входит ли паттерн   в текст  .

Определение:

Будем говорить, что паттерн   встречается в тексте   со сдвигом  , если   и  . Если строка   встречается в строке  , то   является подстрокой  .

[править]Алгоритм

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

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

Приведем пример псевдокода, который находит все вхождения строки   в   и возвращает массив позиций, откуда начинаются вхождения.

vector<int> naiveStringMatcher(t : string, p : string):

int n = t.length

int m = p.length

vector<int> ans

for i = 0 to n - m

if t[i .. i + m - 1] == p

ans.push_back(i)

return ans

[править]Время работы

Алгоритм работает за  . В худшем случае    , что даёт  . Однако если   достаточно мало по сравнению с  , то тогда асимптотика получается близкой к  , поэтому этот алгоритм достаточно широко применяется на практике.

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

[править]Преимущества

  • Требует   памяти.

  • Приемлемое время работы на практике (см. выше). Благодаря этом алгоритм применяется, например, в браузерах и текстовых редакторах (при использовании Ctrl + F), потому что обычно паттерн, который нужно найти, очень короткий по сравнению с самим текстом. Также наивный алгоритм используется в стандартных библиотеках языков высокого уровня (C++, Java), потому что он не требует дополнительной памяти.

  • Простая и понятная реализация.

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