В этой статье блога мы углубимся в различные методы поиска самой длинной палиндромной подпоследовательности (LPS) заданной строки. Палиндромная подпоследовательность — это последовательность, которая остается неизменной при чтении вперед и назад, но не обязательно должна быть непрерывной. Мы рассмотрим различные подходы, включая динамическое программирование, рекурсию с мемоизацией, а также подходы «сверху вниз» и «снизу вверх». Итак, начнём!
- Подход динамического программирования:
Подход динамического программирования — это широко используемый метод эффективного решения проблем путем разбиения их на более мелкие перекрывающиеся подзадачи и сохранения их решений. Вот пример кода на Python:
def longest_palindromic_subsequence(s):
n = len(s)
dp = [[0] * n for _ in range(n)]
for i in range(n):
dp[i][i] = 1
for cl in range(2, n + 1):
for i in range(n - cl + 1):
j = i + cl - 1
if s[i] == s[j] and cl == 2:
dp[i][j] = 2
elif s[i] == s[j]:
dp[i][j] = dp[i + 1][j - 1] + 2
else:
dp[i][j] = max(dp[i][j - 1], dp[i + 1][j])
return dp[0][n - 1]
- Рекурсия с мемоизацией.
Рекурсия с мемоизацией — еще один подход к решению этой проблемы. Он позволяет избежать избыточных вычислений, сохраняя результаты подзадач в кеше. Вот пример того, как это можно реализовать:
def longest_palindromic_subsequence(s):
memo = {}
def dp(i, j):
if i > j:
return 0
if i == j:
return 1
if (i, j) in memo:
return memo[(i, j)]
if s[i] == s[j]:
memo[(i, j)] = dp(i + 1, j - 1) + 2
else:
memo[(i, j)] = max(dp(i + 1, j), dp(i, j - 1))
return memo[(i, j)]
return dp(0, len(s) - 1)
- Нисходящий подход.
Нисходящий подход разбивает проблему на более мелкие подзадачи и решает их рекурсивно, начиная сверху. Вот пример того, как это можно реализовать:
def longest_palindromic_subsequence(s):
n = len(s)
memo = [[-1] * n for _ in range(n)]
def dp(i, j):
if i > j:
return 0
if i == j:
return 1
if memo[i][j] != -1:
return memo[i][j]
if s[i] == s[j]:
memo[i][j] = dp(i + 1, j - 1) + 2
else:
memo[i][j] = max(dp(i + 1, j), dp(i, j - 1))
return memo[i][j]
return dp(0, n - 1)
- Подход «снизу вверх».
Подход «снизу вверх» решает проблему путем итеративного построения решения, начиная с более мелких подзадач и постепенно решая более крупные. Вот пример того, как это можно реализовать:
def longest_palindromic_subsequence(s):
n = len(s)
dp = [[0] * n for _ in range(n)]
for i in range(n):
dp[i][i] = 1
for cl in range(2, n + 1):
for i in range(n - cl + 1):
j = i + cl - 1
if s[i] == s[j]:
dp[i][j] = dp[i + 1][j - 1] + 2
else:
dp[i][j] = max(dp[i][j - 1], dp[i + 1][j])
return dp[0][n - 1]
В этой статье блога мы рассмотрели различные методы поиска самой длинной палиндромной подпоследовательности. Мы рассмотрели подход динамического программирования, рекурсию с запоминанием, а также подходы «сверху вниз» и «снизу вверх». Каждый метод имеет свои преимущества и недостатки в зависимости от размера проблемы и ограничений. Понимая эти методы и их реализации, вы можете эффективно найти самую длинную палиндромную подпоследовательность заданной строки. Независимо от того, предпочитаете ли вы подход динамического программирования, рекурсию с запоминанием или подход «сверху вниз» или «снизу вверх», теперь у вас есть несколько вариантов эффективного решения этой проблемы.