奇怪的打印机
字数 1239 2025-10-30 21:15:36

奇怪的打印机

题目描述

有一台奇怪的打印机,它有两个特殊的功能:

  1. 每次操作,打印机可以打印一段连续的相同字符
  2. 每次操作,打印机可以在已经打印好的字符上覆盖新的字符,但只能覆盖连续的一段字符

给定一个字符串 s,你的任务是找出打印机打印出字符串 s 所需的最少操作次数。

示例

  • 输入:s = "aaabbb"

  • 输出:2

  • 解释:首先打印 "aaa",然后打印 "bbb"

  • 输入:s = "aba"

  • 输出:2

  • 解释:首先打印 "aaa",然后在中间位置覆盖打印 "b"

解题思路

这个问题可以使用区间动态规划来解决。我们需要找到打印整个字符串 s 的最小操作次数。

关键观察

  1. 如果字符串首尾字符相同,那么我们可以先打印整个区间为这个字符,然后处理中间部分
  2. 如果字符串首尾字符不同,我们需要考虑所有可能的分割点

动态规划定义
定义 dp[i][j] 表示打印子串 s[i...j] 所需的最小操作次数。

状态转移方程

  1. 基础情况:当 i == j 时,dp[i][j] = 1(单个字符只需要一次操作)

  2. 当 s[i] == s[j] 时

    • 我们可以先打印整个区间为 s[i] 字符,然后处理内部
    • dp[i][j] = dp[i][j-1] 或 dp[i+1][j]
    • 因为首尾相同,打印最后一个字符时可以"顺便"打印第一个字符
  3. 当 s[i] != s[j] 时

    • 我们需要在区间内找一个分割点 k
    • dp[i][j] = min(dp[i][k] + dp[k+1][j]),其中 i ≤ k < j

详细解题步骤

让我们通过示例 s = "aba" 来详细说明:

步骤1:初始化

  • 创建 dp 表格,大小为 n × n(n = 3)
  • 对角线元素初始化为 1:dp[0][0] = 1, dp[1][1] = 1, dp[2][2] = 1

步骤2:处理长度为2的子串

  • 子串 "ab":s[0] != s[1]
    • dp[0][1] = min(dp[0][0] + dp[1][1]) = 1 + 1 = 2
  • 子串 "ba":s[1] != s[2]
    • dp[1][2] = min(dp[1][1] + dp[2][2]) = 1 + 1 = 2

步骤3:处理长度为3的整个字符串

  • 子串 "aba":s[0] == s[2] ('a' == 'a')
    • dp[0][2] = dp[0][1] = 2
    • 解释:先打印整个区间为 'a'(一次操作),然后在中间覆盖打印 'b'(第二次操作)

最终结果:dp[0][2] = 2

算法实现要点

  1. 按区间长度从小到大计算
  2. 先处理小区间,再处理大区间
  3. 注意边界条件处理

时间复杂度:O(n³)
空间复杂度:O(n²)

这个算法通过动态规划有效地解决了打印机的最少操作次数问题,核心思想是利用区间DP逐步构建最优解。

奇怪的打印机 题目描述 有一台奇怪的打印机,它有两个特殊的功能: 每次操作,打印机可以打印一段连续的相同字符 每次操作,打印机可以在已经打印好的字符上覆盖新的字符,但只能覆盖连续的一段字符 给定一个字符串 s,你的任务是找出打印机打印出字符串 s 所需的最少操作次数。 示例 输入:s = "aaabbb" 输出:2 解释:首先打印 "aaa",然后打印 "bbb" 输入:s = "aba" 输出:2 解释:首先打印 "aaa",然后在中间位置覆盖打印 "b" 解题思路 这个问题可以使用区间动态规划来解决。我们需要找到打印整个字符串 s 的最小操作次数。 关键观察 如果字符串首尾字符相同,那么我们可以先打印整个区间为这个字符,然后处理中间部分 如果字符串首尾字符不同,我们需要考虑所有可能的分割点 动态规划定义 定义 dp[ i][ j] 表示打印子串 s[ i...j ] 所需的最小操作次数。 状态转移方程 基础情况 :当 i == j 时,dp[ i][ j ] = 1(单个字符只需要一次操作) 当 s[ i] == s[ j] 时 : 我们可以先打印整个区间为 s[ i ] 字符,然后处理内部 dp[ i][ j] = dp[ i][ j-1] 或 dp[ i+1][ j ] 因为首尾相同,打印最后一个字符时可以"顺便"打印第一个字符 当 s[ i] != s[ j] 时 : 我们需要在区间内找一个分割点 k dp[ i][ j] = min(dp[ i][ k] + dp[ k+1][ j]),其中 i ≤ k < j 详细解题步骤 让我们通过示例 s = "aba" 来详细说明: 步骤1:初始化 创建 dp 表格,大小为 n × n(n = 3) 对角线元素初始化为 1:dp[ 0][ 0] = 1, dp[ 1][ 1] = 1, dp[ 2][ 2 ] = 1 步骤2:处理长度为2的子串 子串 "ab":s[ 0] != s[ 1 ] dp[ 0][ 1] = min(dp[ 0][ 0] + dp[ 1][ 1 ]) = 1 + 1 = 2 子串 "ba":s[ 1] != s[ 2 ] dp[ 1][ 2] = min(dp[ 1][ 1] + dp[ 2][ 2 ]) = 1 + 1 = 2 步骤3:处理长度为3的整个字符串 子串 "aba":s[ 0] == s[ 2 ] ('a' == 'a') dp[ 0][ 2] = dp[ 0][ 1 ] = 2 解释:先打印整个区间为 'a'(一次操作),然后在中间覆盖打印 'b'(第二次操作) 最终结果 :dp[ 0][ 2 ] = 2 算法实现要点 按区间长度从小到大计算 先处理小区间,再处理大区间 注意边界条件处理 时间复杂度 :O(n³) 空间复杂度 :O(n²) 这个算法通过动态规划有效地解决了打印机的最少操作次数问题,核心思想是利用区间DP逐步构建最优解。