Я пытаюсь решить проблему динамического программирования из Cormem Введение в алгоритмы 3-го издания (стр. 405), в котором предлагается следующее:
Палиндром - это непустая строка над некоторый алфавит, который читает то же самое вперед и назад. Примеры палиндромами являются все строки длины 1,
civic
,racecar
иaibohphobia
(страх перед палиндромами).Дайте эффективный алгоритм для поиска самый длинный палиндром, который является подпоследовательность данной входной строки. Например, учитывая ввод
character
, ваш алгоритм должен returncarac
.
Ну, я мог бы решить это двумя способами:
Первое решение:
Самая длинная подпоследовательность палиндрома (LPS) строки - это просто Самая длинная общая подпоследовательность сама и ее обратная. (Я построил это решение после решения другого связанного вопроса, который запрашивает "Longest Increasing Subsequence" последовательности). Поскольку это просто вариант LCS, он также принимает O (n²) время и память O (n²).
Второе решение:
Второе решение немного более подробно, но также следует за общим шаблоном LCS. Это происходит из следующего повторения:
lps(s[i..j]) =
s[i] + lps(s[i+1]..[j-1]) + s[j], if s[i] == s[j];
max(lps(s[i+1..j]), lps(s[i..j-1])) otherwise
Псевдокод для вычисления длины lps выглядит следующим образом:
compute-lps(s, n):
// palindromes with length 1
for i = 1 to n:
c[i, i] = 1
// palindromes with length up to 2
for i = 1 to n-1:
c[i, i+1] = (s[i] == s[i+1]) ? 2 : 1
// palindromes with length up to j+1
for j = 2 to n-1:
for i = 1 to n-i:
if s[i] == s[i+j]:
c[i, i+j] = 2 + c[i+1, i+j-1]
else:
c[i, i+j] = max( c[i+1, i+j] , c[i, i+j-1] )
По-прежнему требуется O (n²) время и память, если я хочу эффективно построить lps (потому что мне понадобятся все ячейки в таблице). Анализируя связанные проблемы, такие как LIS, которые могут быть решены с помощью подходов, отличных от LCS-подобных с меньшей памятью (LIS разрешима с памятью O (n)), мне было интересно, можно ли решить проблему с памятью O (n) тоже.
LIS достигает этой границы, связывая кандидатные подпоследовательности, но с палиндромами это сложнее, потому что здесь важно не предыдущий элемент в подпоследовательности, а первый. Кто-нибудь знает, возможно ли это сделать, или оптимальная память предыдущих решений?