区间动态规划例题:带权重的字符串交织问题(最小化交织成本)
字数 2608 2025-12-20 05:41:41

区间动态规划例题:带权重的字符串交织问题(最小化交织成本)


题目描述

给定三个字符串:ABC,以及一个成本函数 cost(i, j, k),其中 ijk 分别是 ABC 的索引。
字符串 C 的长度为 n + m(其中 n = len(A), m = len(B))。我们需要判断 C 是否可以通过交织 AB 得到(保持 AB 的字符顺序不变),并计算最小交织成本。

交织成本定义为:
当选择 A 的第 i 个字符匹配 C 的某个位置时,产生成本 cost(i, -1, k)
当选择 B 的第 j 个字符匹配 C 的某个位置时,产生成本 cost(-1, j, k)
目标是使总成本最小。


解题思路

这是一个区间动态规划问题,因为 CAB 的交织,我们可以逐步匹配 C 的字符到 AB 中。
状态定义:
dp[i][j] 表示用 A 的前 i 个字符和 B 的前 j 个字符,匹配到 C 的前 (i + j) 个字符时的最小成本。

状态转移:

  • 如果 A[i-1] == C[i+j-1],那么可以从 dp[i-1][j] 转移过来,加上成本 cost(i-1, -1, i+j-1)
  • 如果 B[j-1] == C[i+j-1],那么可以从 dp[i][j-1] 转移过来,加上成本 cost(-1, j-1, i+j-1)
  • 如果两个条件都满足,取成本较小的转移。

初始化:
dp[0][0] = 0(空字符串匹配空字符串)。
第一行和第一列需要单独初始化,表示只用 A 或只用 B 匹配 C 的情况。

答案:
dp[n][m] 即为最小交织成本。如果无法交织,则设置为无穷大。


循序渐进讲解

步骤1:定义状态

我们定义 dp[i][j]

  • i 表示已经使用了 A 的前 i 个字符(0 ≤ i ≤ n)。
  • j 表示已经使用了 B 的前 j 个字符(0 ≤ j ≤ m)。
  • dp[i][j] 表示匹配到 C 的前 (i+j) 个字符时的最小成本。

注意:C 的长度为 n+m,所以只有当 i+jC 的位置对应时才有意义。


步骤2:状态转移方程

对于 dp[i][j],我们考虑 C 的第 (i+j) 个字符(索引为 i+j-1)是从 A 还是从 B 来的:

  1. 如果 i > 0A[i-1] == C[i+j-1]
    说明当前字符可以来自 A 的第 i 个字符。
    那么,匹配到前 (i+j) 个字符的最小成本 = dp[i-1][j] + cost(i-1, -1, i+j-1)

  2. 如果 j > 0B[j-1] == C[i+j-1]
    说明当前字符可以来自 B 的第 j 个字符。
    那么,匹配到前 (i+j) 个字符的最小成本 = dp[i][j-1] + cost(-1, j-1, i+j-1)

  3. 如果两个条件都满足,取两者中的较小值。
    如果都不满足,则 dp[i][j] = INF(表示无法匹配)。

转移方程:

dp[i][j] = min(
    (dp[i-1][j] + cost(i-1, -1, i+j-1)) if i>0 and A[i-1]==C[i+j-1] else INF,
    (dp[i][j-1] + cost(-1, j-1, i+j-1)) if j>0 and B[j-1]==C[i+j-1] else INF
)

步骤3:初始化

  • dp[0][0] = 0:空字符串匹配空字符串,成本为0。
  • 初始化第一行 dp[0][j](只用 B 匹配 C):
    需要检查 B 的前 j 个字符是否依次等于 C 的前 j 个字符,并且累加成本。
    如果有任何一个字符不匹配,则 dp[0][j] = INF
  • 初始化第一列 dp[i][0](只用 A 匹配 C):同理。

示例:

for j in range(1, m+1):
    if B[j-1] == C[j-1]:
        dp[0][j] = dp[0][j-1] + cost(-1, j-1, j-1)
    else:
        dp[0][j] = INF

类似地处理 dp[i][0]


步骤4:填表计算

i0nj0m 的顺序填表(注意 ij 不能同时为0)。
对于每个 (i, j),根据状态转移方程计算。


步骤5:输出答案

如果 dp[n][m] 为无穷大,则表示无法交织得到 C
否则,dp[n][m] 即为最小交织成本。


举例说明

假设:

  • A = "ab", B = "bc", C = "abbc"
  • 成本函数简化:每次匹配的成本为0(即只判断能否交织,不求最小成本)。

步骤:

  1. 初始化 dp[0][0]=0
  2. 初始化第一行:B 的前1个字符 "b"C[0]='a' 不匹配 → dp[0][1]=INF,后面都为 INF
  3. 初始化第一列:A 的前1个字符 "a"C[0]='a' 匹配 → dp[1][0] = dp[0][0] + 0 = 0
    A 的前2个字符 "ab"C[0..1]="ab" 匹配 → dp[2][0] = dp[1][0] + 0 = 0
  4. 计算 dp[1][1]
    • 来自 AA[0]='a'C[1]='b' 不匹配,不可行。
    • 来自 BB[0]='b'C[1]='b' 匹配,且 dp[1][0]=0 → 成本0。
      所以 dp[1][1] = 0
  5. 继续计算直到 dp[2][2]
    • 最终状态 dp[2][2] 应为0,表示可以交织得到 C

复杂度分析

  • 时间复杂度:O(n × m),需要填充二维表格。
  • 空间复杂度:O(n × m),可以使用滚动数组优化到 O(m) 或 O(n)。

关键点总结

  1. 状态设计:dp[i][j] 表示用 A 的前 i 个和 B 的前 j 个匹配 C 的前 (i+j) 个字符的最小成本。
  2. 转移条件:必须检查当前字符是否与 AB 的对应字符相等。
  3. 初始化:第一行和第一列需要单独处理,因为它们代表只用 A 或只用 B 的情况。
  4. 答案:dp[n][m] 是否为无穷大判断可行性,否则为最小成本。

这样,我们就完成了带权重的字符串交织问题的动态规划解法。通过状态转移逐步匹配字符,并累加成本,最终得到最小交织成本。

区间动态规划例题:带权重的字符串交织问题(最小化交织成本) 题目描述 给定三个字符串: A 、 B 和 C ,以及一个成本函数 cost(i, j, k) ,其中 i 、 j 、 k 分别是 A 、 B 、 C 的索引。 字符串 C 的长度为 n + m (其中 n = len(A) , m = len(B) )。我们需要判断 C 是否可以通过交织 A 和 B 得到(保持 A 和 B 的字符顺序不变),并计算最小交织成本。 交织成本定义为: 当选择 A 的第 i 个字符匹配 C 的某个位置时,产生成本 cost(i, -1, k) ; 当选择 B 的第 j 个字符匹配 C 的某个位置时,产生成本 cost(-1, j, k) 。 目标是使总成本最小。 解题思路 这是一个区间动态规划问题,因为 C 是 A 和 B 的交织,我们可以逐步匹配 C 的字符到 A 或 B 中。 状态定义: dp[i][j] 表示用 A 的前 i 个字符和 B 的前 j 个字符,匹配到 C 的前 (i + j) 个字符时的最小成本。 状态转移: 如果 A[i-1] == C[i+j-1] ,那么可以从 dp[i-1][j] 转移过来,加上成本 cost(i-1, -1, i+j-1) 。 如果 B[j-1] == C[i+j-1] ,那么可以从 dp[i][j-1] 转移过来,加上成本 cost(-1, j-1, i+j-1) 。 如果两个条件都满足,取成本较小的转移。 初始化: dp[0][0] = 0 (空字符串匹配空字符串)。 第一行和第一列需要单独初始化,表示只用 A 或只用 B 匹配 C 的情况。 答案: dp[n][m] 即为最小交织成本。如果无法交织,则设置为无穷大。 循序渐进讲解 步骤1:定义状态 我们定义 dp[i][j] : i 表示已经使用了 A 的前 i 个字符(0 ≤ i ≤ n)。 j 表示已经使用了 B 的前 j 个字符(0 ≤ j ≤ m)。 dp[i][j] 表示匹配到 C 的前 (i+j) 个字符时的最小成本。 注意: C 的长度为 n+m ,所以只有当 i+j 与 C 的位置对应时才有意义。 步骤2:状态转移方程 对于 dp[i][j] ,我们考虑 C 的第 (i+j) 个字符(索引为 i+j-1 )是从 A 还是从 B 来的: 如果 i > 0 且 A[i-1] == C[i+j-1] : 说明当前字符可以来自 A 的第 i 个字符。 那么,匹配到前 (i+j) 个字符的最小成本 = dp[i-1][j] + cost(i-1, -1, i+j-1) 。 如果 j > 0 且 B[j-1] == C[i+j-1] : 说明当前字符可以来自 B 的第 j 个字符。 那么,匹配到前 (i+j) 个字符的最小成本 = dp[i][j-1] + cost(-1, j-1, i+j-1) 。 如果两个条件都满足,取两者中的较小值。 如果都不满足,则 dp[i][j] = INF (表示无法匹配)。 转移方程: 步骤3:初始化 dp[0][0] = 0 :空字符串匹配空字符串,成本为0。 初始化第一行 dp[0][j] (只用 B 匹配 C ): 需要检查 B 的前 j 个字符是否依次等于 C 的前 j 个字符,并且累加成本。 如果有任何一个字符不匹配,则 dp[0][j] = INF 。 初始化第一列 dp[i][0] (只用 A 匹配 C ):同理。 示例: 类似地处理 dp[i][0] 。 步骤4:填表计算 按 i 从 0 到 n , j 从 0 到 m 的顺序填表(注意 i 和 j 不能同时为0)。 对于每个 (i, j) ,根据状态转移方程计算。 步骤5:输出答案 如果 dp[n][m] 为无穷大,则表示无法交织得到 C ; 否则, dp[n][m] 即为最小交织成本。 举例说明 假设: A = "ab" , B = "bc" , C = "abbc" 成本函数简化:每次匹配的成本为0(即只判断能否交织,不求最小成本)。 步骤: 初始化 dp[0][0]=0 。 初始化第一行: B 的前1个字符 "b" 与 C[0]='a' 不匹配 → dp[0][1]=INF ,后面都为 INF 。 初始化第一列: A 的前1个字符 "a" 与 C[0]='a' 匹配 → dp[1][0] = dp[0][0] + 0 = 0 。 A 的前2个字符 "ab" 与 C[0..1]="ab" 匹配 → dp[2][0] = dp[1][0] + 0 = 0 。 计算 dp[1][1] : 来自 A : A[0]='a' 与 C[1]='b' 不匹配,不可行。 来自 B : B[0]='b' 与 C[1]='b' 匹配,且 dp[1][0]=0 → 成本0。 所以 dp[1][1] = 0 。 继续计算直到 dp[2][2] : 最终状态 dp[2][2] 应为0,表示可以交织得到 C 。 复杂度分析 时间复杂度:O(n × m),需要填充二维表格。 空间复杂度:O(n × m),可以使用滚动数组优化到 O(m) 或 O(n)。 关键点总结 状态设计: dp[i][j] 表示用 A 的前 i 个和 B 的前 j 个匹配 C 的前 (i+j) 个字符的最小成本。 转移条件:必须检查当前字符是否与 A 或 B 的对应字符相等。 初始化:第一行和第一列需要单独处理,因为它们代表只用 A 或只用 B 的情况。 答案: dp[n][m] 是否为无穷大判断可行性,否则为最小成本。 这样,我们就完成了带权重的字符串交织问题的动态规划解法。通过状态转移逐步匹配字符,并累加成本,最终得到最小交织成本。