📅  最后修改于: 2023-12-03 15:10:37.694000             🧑  作者: Mango
这道题目可以使用动态规划的思想来解决。我们可以用 $dp[i][j]$ 来表示以第 $i$ 个字符结尾,最后两个字符为 $j$ 的最长子序列长度。其中,$j$ 的取值可以为 $0,1,2$,分别表示该位置字符尚未出现过、已经出现过并且当前字符与上一个字符相同、已经出现过并且当前字符与上一个字符不同。
那么,根据题目要求,我们可以列出如下转移方程:
$$ dp[i][0]=\max(dp[i-1][0],dp[i-1][1],dp[i-1][2]) + 1 ;;;;(\text{if } s_i \neq s_{i-1}) $$
$$ dp[i][1]=\max(dp[i-1][0],dp[i-1][2]) + 1 ;;;;(\text{if } s_i = s_{i-1}\land s_i \neq s_{i-2}) $$
$$ dp[i][2]=\max(dp[i-1][0],dp[i-1][1]) + 1 ;;;;(\text{if } s_i = s_{i-1}\land s_i = s_{i-2}) $$
其中,$s_i$ 表示第 $i$ 个字符。
最终的答案就是 $\max(dp[i][0],dp[i][1],dp[i][2])$,其中 $i$ 的取值范围是 $1\sim n$,$n$ 是字符串的长度。
下面是一份基于 Python 的实现代码:
def longest_subsequence(s: str) -> int:
n = len(s)
dp = [[0] * 3 for _ in range(n + 1)]
for i in range(1, n + 1):
if s[i - 1] != s[i - 2]:
dp[i][0] = max(dp[i - 1])
dp[i][0] = max(dp[i][0], dp[i][0] + 1)
if i >= 3 and s[i - 1] == s[i - 2] and s[i - 3] != s[i - 1]:
dp[i][1] = max(dp[i - 1][0], dp[i - 1][2])
dp[i][1] = max(dp[i][1], dp[i][1] + 1)
if i >= 3 and s[i - 1] == s[i - 2] and s[i - 1] == s[i - 3]:
dp[i][2] = max(dp[i - 1][0], dp[i - 1][1])
dp[i][2] = max(dp[i][2], dp[i][2] + 1)
return max(dp[n])
该代码的时间复杂度是 $O(n)$,空间复杂度是 $O(n)$。