📜  门| GATE CS 2021 |设置1 |问题12(1)

📅  最后修改于: 2023-12-03 14:58:22.133000             🧑  作者: Mango

门| GATE CS 2021 |设置1 |问题12

问题:给定一个字符串S,找出它是否是回文。如果是回文,找到能够从该字符串中删除的最小数量的字符,使得剩余字符串是回文。

例如,字符串"SATURDAY"可以被转换为字符串"UTUT",删除了4个字符,所以答案为4。

解决方法

我们可以使用动态规划的方法来解决这个问题。首先,定义dp[i][j]为字符串[i:j]是否为回文。如果是回文,dp[i][j]为True,否则为False。

以字符串"SATURDAY"为例,构建如下动态规划矩阵:

| | S | A | T | U | R | D | A | Y | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | S | T | F | F | F | F | F | F | F | | A | | U | F | F | F | F | F | F | | T | | | T | F | F | F | F | F | | U | | | | T | F | F | F | F | | R | | | | | T | F | F | F | | D | | | | | | T | F | F | | A | | | | | | | T | F | | Y | | | | | | | | T |

对于长度为1的字符串,即 dp[i][i],它一定是回文,dp[i][i] = True。

对于长度为2的字符串,即 dp[i][i+1],如果s[i] == s[i+1],那么它是回文,dp[i][i+1] = True,否则它不是回文,dp[i][i+1] = False。

对于长度大于等于3的字符串,即 dp[i][j],如果s[i] == s[j] 并且 dp[i+1][j-1]为True,那么它是回文,dp[i][j] = True,否则它不是回文,dp[i][j] = False。

接下来,我们需要找到能够从该字符串中删除的最小数量的字符,使得剩余字符串是回文。

定义dp2[i][j]为字符串[i:j]中,能够删除的最小数量的字符,使得剩余字符串是回文。

当 s[i] == s[j] 时,dp2[i][j] = dp2[i+1][j-1]。因为我们可以同时删除 i 和 j,而不会影响字符串[i+1:j-1]的回文性质。

当 s[i] != s[j] 时,我们有两种选择:

  • 删除 s[i],使得字符串[i+1:j] 回文。此时,dp2[i][j] = dp2[i+1][j] + 1。
  • 删除 s[j],使得字符串[i:j-1] 回文。此时,dp2[i][j] = dp2[i][j-1] + 1。

综上所述,我们可以得到以下解决方案:

def minimum_deletions_palindrome(s: str) -> int:
    n = len(s)
    dp = [[False] * n for _ in range(n)]
    dp2 = [[0] * n for _ in range(n)]

    # length 1
    for i in range(n):
        dp[i][i] = True

    # length 2
    for i in range(n-1):
        if s[i] == s[i+1]:
            dp[i][i+1] = True
        else:
            dp2[i][i+1] = 1

    # length >= 3
    for l in range(3, n+1):
        for i in range(n-l+1):
            j = i + l - 1
            if s[i] == s[j] and dp[i+1][j-1]:
                dp[i][j] = True
            if not dp[i][j]:
                dp2[i][j] = min(dp2[i+1][j] + 1, dp2[i][j-1] + 1)

    return dp2[0][-1]

时间复杂度为 O(n^2),空间复杂度为 O(n^2)。

希望这篇文章能够对你有所帮助。