Я пытаюсь решить проблему динамического программирования из 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 достигает этой границы, связывая кандидатные подпоследовательности, но с палиндромами это сложнее, потому что здесь важно не предыдущий элемент в подпоследовательности, а первый. Кто-нибудь знает, возможно ли это сделать, или оптимальная память предыдущих решений?