📌  相关文章
📜  最长子序列,使得没有 3 个连续字符相同(1)

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

最长子序列,使得没有 3 个连续字符相同

这道题目可以使用动态规划的思想来解决。我们可以用 $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)$。