📌  相关文章
📜  国际空间研究组织 | ISRO CS 2008 |问题 53(1)

📅  最后修改于: 2023-12-03 15:23:02.614000             🧑  作者: Mango

国际空间研究组织 | ISRO CS 2008 | 问题 53

题目描述

给定一个字符串 S,求出S中最长回文子序列的长度。

输入格式
  • 第一行包含一个整数 N,表示字符串 S 的长度。
  • 第二行包含字符串 S。
输出格式

输出一个整数,表示字符串 S 的最长回文子序列的长度。

输入样例
10
BBABCBCAB
输出样例
7
算法思路

本题可采用动态规划的思路。

设 $dp[i][j]$ 表示字符串 $S$ 的第 $i$ 到第 $j$ 个字符组成的子串中,最长回文子序列的长度。

当 $i=j$ 时,$dp[i][i]=1$。

当 $i<j$ 时,若 $S_i=S_j$,则 $dp[i][j]=dp[i+1][j-1]+2$;否则,$dp[i][j]=\max{dp[i+1][j],dp[i][j-1]}$。

因此,我们可以先按照字符串的长度从小到大依次求出所有长度的回文子序列,最终得到整个字符串的最长回文子序列。

代码实现
def lps(s: str) -> int:
    n = len(s)
    dp = [[0] * n for _ in range(n)]
    for i in range(n):
        dp[i][i] = 1
    for l in range(2, n + 1):
        for i in range(n - l + 1):
            j = i + l - 1
            if s[i] == s[j]:
                dp[i][j] = dp[i + 1][j - 1] + 2
            else:
                dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])
    return dp[0][n - 1]

if __name__ == '__main__':
    n = int(input().strip())
    s = input().strip()
    print(lps(s))

其中,lps(s: str) -> int 函数实现了回文子序列的长度计算。

dp[i][j] 表示字符串 $S$ 的第 $i$ 到第 $j$ 个字符组成的子串中,最长回文子序列的长度。

状态转移方程为:

  • 当 $i=j$ 时,$dp[i][i]=1$。
  • 当 $i<j$ 时,若 $S_i=S_j$,则 $dp[i][j]=dp[i+1][j-1]+2$;否则,$dp[i][j]=\max{dp[i+1][j],dp[i][j-1]}$。

最终,返回 $dp[0][n-1]$ 即可。