Самая длинная общая подстрока
В информатике самая длинная общая подстрока из двух или более строк — это самая длинная строка , которая является подстрокой всех из них. Может существовать более одной самой длинной общей подстроки. Приложения включают дедупликацию данных и обнаружение плагиата .
Примеры
[ редактировать ]На рисунке показаны две строки, где задача имеет несколько решений. Хотя вхождения подстроки всегда перекрываются, невозможно получить более длинную общую подстроку, «объединив» их.
Строки «ABABC», «BABCA» и «ABCBA» имеют только одну самую длинную общую подстроку, а именно. «ABC» длиной 3. Другими распространенными подстроками являются «A», «AB», «B», «BA», «BC» и «C».
ABABC ||| BABCA ||| ABCBA
Определение проблемы
[ редактировать ]Учитывая две строки, длины и длины , найдите самую длинную строку, которая является подстрокой обеих и .
Обобщением является задача о k - общих подстроках . Учитывая набор строк , где и . Найдите для каждого , самая длинная строка, которая встречается как подстрока как минимум струны.
Алгоритмы
[ редактировать ]Можно найти длины и начальные позиции самых длинных общих подстрок и в время с помощью обобщенного суффиксного дерева . Более быстрый алгоритм может быть достигнут в модели вычислений со словным ОЗУ , если размер входного алфавита находится в . В частности, этот алгоритм работает в время использования космос. [1] Решение проблемы за счет на динамическое программирование затрат . Решение обобщенной задачи принимает пространство и время с динамическим программированием и принять время с обобщенным суффиксным деревом .
Суффиксное дерево
[ редактировать ]Самые длинные общие подстроки набора строк можно найти, построив обобщенное суффиксное дерево для строк, а затем найдя самые глубокие внутренние узлы, имеющие конечные узлы из всех строк в поддереве ниже него. Рисунок справа представляет собой суффиксное дерево строк «ABAB», «BABA» и «ABBA», дополненное уникальными символами завершения строки, чтобы превратиться в «ABAB$0», «BABA$1» и «ABBA$2». Узлы, представляющие «A», «B», «AB» и «BA», имеют листья-потомки всех строк с номерами 0, 1 и 2.
Построение суффиксного дерева занимает время (если размер алфавита постоянный). Если дерево обходится снизу вверх с помощью битового вектора, указывающего, какие строки находятся под каждым узлом, проблема k-общих подстрок может быть решена в время. Если суффиксное дерево подготовлено для поиска наименьшего общего предка за постоянное время , его можно решить в время. [2]
Динамическое программирование
[ редактировать ]Следующий псевдокод находит набор самых длинных общих подстрок между двумя строками с помощью динамического программирования:
function LongestCommonSubstring(S[1..r], T[1..n]) L := array(1..r, 1..n) z := 0 ret := {} for i := 1..r for j := 1..n if S[i] = T[j] if i = 1 or j = 1 L[i, j] := 1 else L[i, j] := L[i − 1, j − 1] + 1 if L[i, j] > z z := L[i, j] ret := {S[i − z + 1..i]} else if L[i, j] = z ret := ret ∪ {S[i − z + 1..i]} else L[i, j] := 0 return ret
Этот алгоритм работает в время. Массив L
хранит длину самой длинной общей подстроки префиксов S[1..i]
и T[1..j]
которые заканчиваются на позиции i
и j
, соответственно. Переменная z
используется для хранения длины самой длинной общей подстроки, найденной на данный момент. Набор ret
используется для хранения набора строк длиной z
. Набор ret
можно эффективно сохранить, просто сохранив индекс i
, который является последним символом самой длинной общей подстроки (размера z) вместо S[i-z+1..i]
. Таким образом, все самые длинные общие подстроки будут для каждого i в ret
, S[(ret[i]-z)..(ret[i])]
.
Следующие приемы можно использовать для уменьшения использования памяти реализацией:
- Для экономии памяти оставьте только последнюю и текущую строку таблицы DP ( вместо )
- Последняя и текущая строки могут быть сохранены в одном и том же одномерном массиве, пройдя внутренний цикл назад.
- Сохраняйте в строках только ненулевые значения. Это можно сделать, используя хеш-таблицы вместо массивов. Это полезно для больших алфавитов.
См. также
[ редактировать ]- Самая длинная палиндромная подстрока
- n -gram , все возможные подстроки длины n , содержащиеся в строке
Ссылки
[ редактировать ]- ^ Харалампопулос, Панайотис; Коцюмака, Томаш; Писсис, Солон П.; Радошевский, Якуб (август 2021 г.). Мюцель, Петра; Паг, Расмус; Герман, Гжегож (ред.). Более быстрые алгоритмы для поиска самой длинной общей подстроки . Европейский симпозиум по алгоритмам. Международные труды Лейбница по информатике (LIPIcs). Том. 204. Замок Дагштуль. doi : 10.4230/LIPIcs.ESA.2021.30 . Здесь: Теорема 1, стр.30:2.
- ^ Гасфилд, Дэн (1999) [1997]. Алгоритмы на строках, деревьях и последовательностях: информатика и вычислительная биология . США: Издательство Кембриджского университета. ISBN 0-521-58519-8 .
Внешние ссылки
[ редактировать ]- Словарь алгоритмов и структур данных: самая длинная общая подстрока
- Perl/XS реализация алгоритма динамического программирования
- Perl/XS реализация алгоритма суффиксного дерева
- Реализации динамического программирования на разных языках в викибуках
- рабочая реализация AS3 алгоритма динамического программирования
- Реализация C на основе суффиксного дерева самой длинной общей подстроки для двух строк