Нахождение самой длинной повторяющейся подпоследовательности


9

Учитывая строку , я хотел бы найти самую длинную повторяющуюся (по крайней мере дважды) подпоследовательность. То есть я хотел бы найти строку которая является подпоследовательностью (не обязательно должна быть смежной) такой что . То есть - это строка, половинки которой появляются дважды подряд. Обратите внимание, что является подпоследовательностью , но не обязательно подстрокой.swsw=wwwws

Примеры:

Для «ababccabdc» это будет «abcabc», потому что «abc» = «abc» и «abc» появляются (как минимум) дважды в «ababccabdc».

Для 'addbacddabcd' одним из вариантов является 'dddd', потому что 'dd' появляется дважды (я не могу использовать одну и ту же букву несколько раз, но здесь у меня 4 'd, так что все в порядке), но его длина 4. Я могу найти лучший длины 8: «abcdabcd», потому что «abcd» является подстрокой «addbacddabcd», которая появляется дважды.

Я заинтересован в поиске самой длинной повторяющейся подпоследовательности. Это также называется «найти самый длинный / самый большой квадрат», но я читал много статей, в которых квадрат определен для подстроки, а не для подпоследовательности.

Я могу легко использовать алгоритм грубой силы, который примет , итерируя по всем параметрам для точки останова в строке, и тогда у меня будет две строки, в которых я буду искать самую большую / самую длинную общую подпоследовательность, но каждая проверка будет принимать с использованием техники динамического программирования, поэтому все время будет . Я нашел более эффективный алгоритм для самой длинной общей подпоследовательности, который принимает , поэтому время выполнения будет .O(n3)O(n2)O(n3)O(n2logn)O(n3logn)

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

Я искал во многих журналах и предыдущих вопросах, и большинство результатов, которые я нашел, было о подстроке, а не о подпоследовательности.

Я также читал, что это можно сделать с помощью суффиксных деревьев, но это также относилось к подстрокам, и я не уверен, что такая идея может быть расширена для подпоследовательности.

Я ищу решение, которое выполняется за время . Если существует одно время , это будет еще лучше (я не уверен, что таковое существует).O ( n log n )O(n2)O(nlogn)


4
Посмотрите деревья суффиксов или массивы суффиксов.
псевдоним

1
Это очень маловероятно , что -время существует алгоритм для этой задачи, так как если это так, вы можете использовать его , чтобы побить лучший известный алгоритм поиска LCS двух длина- строк и следующим образом : Сформируйте строку , где - это копия символа , которого нет ни в ни в , а затем запустите на нем свой алгоритм -time. Обе «половины» самой длинной повторяющейся подпоследовательности обязательно начнутся с , поэтому одна половина приходит от каждого из иo(n2)nuvxuxvxn+1$uvo(n2)xuv, решая проблему LCS.
j_random_hacker

@j_random_hacker LCS может быть решена в с использованием Suffix Tree или в с использованием скользящих хешей. O(n+m)O(nlogn)
зло

@Evil: я еще не вижу, как, не могли бы вы дать немного больше деталей? (Вы уверены, что не думаете о Longest Common Sub string , которая может быть решена в тех временных сложностях?)
j_random_hacker

@j_random_hacker Я думал, что вы сравниваете target с LCS (последовательным), но здесь, как вы упомянули, да, я даже не видел рабочего решения в n ^ 2 для Longest Common Subsequence (я нашел один динамический программный код, распространяющийся по многим страницам, который имеет недостатки, аналогично ответу с пониженным голосом). Так что просто я неправильно понял ваш комментарий, извините. o(n2)
Зло

Ответы:


-1

Вот решение динамического программирования.

Предположим, что входной строкой является . Создайте таблицу , строки и столбцы которой проиндексированы по (где - длина строки), заполненная правилом Ответ - . T 0 , , n n T [ i , j ] = { 0, если  i = 0  или  j = 0x1xnT0,,nnT[n,n]

T[i,j]={0if i=0 or j=0,T[i1,j1]+1if xi=xj and ij,max(T[i1,j],T[i,j1])otherwise.
T[n,n]

Предположим, что мы находимся в некотором с , и условие в вашем утверждении верно. Тогда подразумевается, что символ в позиции является частью обеих подпоследовательностей. i = j + 1 i - 1 = ji,ji=j+1ifdp[i][j] = dp[i - 1][j - 1] + 1i1=j
j_random_hacker

3
Добро пожаловать в информатику! Пожалуйста, избавьтесь от исходного кода и замените его идеями, псевдокодом и аргументами правильности. Смотрите здесь и здесь для связанных мета-обсуждений.
Рафаэль

@Raphael Рекурсивная формула не считается исходным кодом.
Number945

1
@BreakingBenjamin В зависимости от вашего языка вы можете записать данное повторение более или менее буквально. Дело в том, что здесь нет объяснения.
Рафаэль
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.