合并相邻字符的最小成本问题(相邻字符可合并为指定新字符,带权值)
字数 2902 2025-12-22 12:36:02

合并相邻字符的最小成本问题(相邻字符可合并为指定新字符,带权值)


一、题目描述

给你一个长度为 n 的字符串 s,以及一个 合并规则表 cost,其中 cost[a][b] 表示将两个相邻字符 a 和 b 合并成一个新字符 c 的代价,并且合并后产生的新字符 c 是已知的(例如通过另一个映射表给出)。
你需要通过一系列合并操作,将整个字符串最终合并为 单个字符,求 最小总代价

更形式化地说

  • 输入:
    1. 字符串 s,长度 n,字符来自有限字符集 Σ。
    2. 一个函数 nextChar(a, b) 返回合并 a 和 b 得到的新字符。
    3. 一个函数 mergeCost(a, b) 返回合并 a 和 b 的代价(非负整数)。
  • 操作:每次选择相邻的两个字符 x 和 y,花费 mergeCost(x, y),并将它们替换为 newChar = nextChar(x, y)。
  • 目标:将整个字符串合并到只剩一个字符,求最小总代价。

注意:合并的顺序不同,总代价可能不同。

示例(假设字符集为 {A, B, C}):
s = "ABC"
nextChar 规则:
A+B→C, 代价 10
B+C→A, 代价 20
A+C→B, 代价 15
(其他组合可假设代价很大,但题目一般会给出完整表格)。
问最小总代价。


二、问题分析与区间 DP 思路

这个问题是典型的“合并相邻元素”类型,与“石子合并”相似,但区别在于:

  1. 合并后产生的新字符与原来的两个字符不同。
  2. 因此最终合并得到的单个字符是什么,取决于合并顺序。

状态设计
定义 dp[l][r][c] = 将区间 [l, r] 合并成一个字符 c 所需的最小代价。
如果不可能合并成 c,则为无穷大。

l, r 是字符串下标(1‑based 或 0‑based 均可),c 是字符集中的一个字符。

最终答案
min{ dp[1][n][c] | c ∈ Σ }


三、状态转移方程推导

区间 [l, r] 要合并成字符 c,那么最后一次合并一定是将 [l, k] 合并成某个字符 a,[k+1, r] 合并成某个字符 b,并且 nextChar(a, b) = c,合并代价为 mergeCost(a, b)。

所以:
dp[l][r][c] = min{
dp[l][k][a] + dp[k+1][r][b] + mergeCost(a, b)
}
其中:

  • k 从 l 到 r-1 枚举(分割点),
  • a, b 枚举所有字符。

初始条件
区间长度为 1 时,dp[l][l][s[l]] = 0(因为已经就是该字符,无需合并),
对于其他字符 ch ≠ s[l],dp[l][l][ch] = INF(不可能变成别的字符)。


四、DP 计算顺序

因为区间长度 len 从 2 到 n 递推:

  1. 枚举起点 l,r = l+len-1。
  2. 枚举分割点 k ∈ [l, r-1]。
  3. 枚举 a ∈ Σ, b ∈ Σ。
  4. 如果 dp[l][k][a] 和 dp[k+1][r][b] 都不是 INF,则计算 c = nextChar(a, b),
    更新 dp[l][r][c] = min(dp[l][r][c], dp[l][k][a] + dp[k+1][r][b] + mergeCost(a, b))。

复杂度:O(n³·|Σ|³),如果 |Σ| 很小(比如 26 或更小),可以接受。


五、例子推演

假设字符集 Σ = {0, 1, 2},字符串 s = "012",规则:
nextChar 表:
0+1→2, cost=5
1+2→0, cost=3
0+2→1, cost=4
(其他组合假设不可能,代价 INF)

初始:
dp[1][1][0] = 0, dp[2][2][1] = 0, dp[3][3][2] = 0,其余 INF。

len=2
区间 [1,2]:字符 0 和 1,可合并为 2,代价 5,
dp[1][2][2] = dp[1][1][0] + dp[2][2][1] + 5 = 0+0+5 = 5。

区间 [2,3]:字符 1 和 2,可合并为 0,代价 3,
dp[2][3][0] = dp[2][2][1] + dp[3][3][2] + 3 = 0+0+3 = 3。

len=3
区间 [1,3],枚举 k=1 或 k=2。

k=1:
左边 [1,1]→{0},右边 [2,3]→{0}(但注意 [2,3] 只能变成 0,因 1+2→0),
a=0, b=0,查表 0+0 无定义(假设不可合并),跳过。
左边 {0} 与右边 {0} 无法合并成 Σ 中任何字符,无更新。

k=2:
左边 [1,2]→{2},右边 [3,3]→{2},
a=2, b=2,2+2 无定义,跳过。
但实际上左边 [1,2] 只能变成 2,右边是字符 2,2+2 不可合并,所以不行。
但还有别的 a,b 吗?我们只存储了 [1,2] 变成 2 的可能,所以只有 a=2, b=2 这一对,不可合并。
难道无解?检查:
合并顺序1:先合并 0 1 得到 2(代价5),字符串变 "22",然后 2+2 无定义,失败。
合并顺序2:先合并 1 2 得到 0(代价3),字符串变 "00",然后 0+0 无定义,失败。
所以这个例子中,无法合并成单个字符?

说明规则表必须保证任何两个字符都能合并成某个字符(即合并是封闭的),否则可能无解。

我们修正规则,假设 0+0→0, 1+1→1, 2+2→2,代价 0。
那么:
dp[2][3][0] = 3 仍成立。
现在 len=3, k=2:
左边 [1,2]→{2},右边 [3,3]→{2},
a=2, b=2,合并 2+2→2 代价 0,
c=2,
dp[1][3][2] = min(INF, dp[1][2][2] + dp[3][3][2] + 0) = 5+0+0 = 5。

k=1:
左边 [1,1]→{0},右边 [2,3]→{0},
0+0→0 代价 0,
dp[1][3][0] = 0 + 3 + 0 = 3。

所以最终答案是 min(dp[1][3][0], dp[1][3][2]) = min(3, 5) = 3。


六、总结

本题是区间 DP 的一个变体,关键点是状态中要记录合并成的字符,因为合并结果影响后续合并。
它和“石子合并”的差异在于结果字符变化,因此状态维度多了一维(字符)。
常用于模拟某些化学分子结合、符号表达式化简等问题。

如果你在题目中看到“每次合并相邻两个符号,根据规则生成新符号,并付出代价,求合并到单个符号的最小代价”,就是此类问题。

合并相邻字符的最小成本问题(相邻字符可合并为指定新字符,带权值) 一、题目描述 给你一个长度为 n 的字符串 s,以及一个 合并规则表 cost,其中 cost[ a][ b ] 表示将两个相邻字符 a 和 b 合并成一个新字符 c 的代价,并且合并后产生的新字符 c 是已知的(例如通过另一个映射表给出)。 你需要通过一系列合并操作,将整个字符串最终合并为 单个字符 ,求 最小总代价 。 更形式化地说 : 输入: 字符串 s,长度 n,字符来自有限字符集 Σ。 一个函数 nextChar(a, b) 返回合并 a 和 b 得到的新字符。 一个函数 mergeCost(a, b) 返回合并 a 和 b 的代价(非负整数)。 操作:每次选择相邻的两个字符 x 和 y,花费 mergeCost(x, y),并将它们替换为 newChar = nextChar(x, y)。 目标:将整个字符串合并到只剩一个字符,求最小总代价。 注意 :合并的顺序不同,总代价可能不同。 示例(假设字符集为 {A, B, C}): s = "ABC" nextChar 规则: A+B→C, 代价 10 B+C→A, 代价 20 A+C→B, 代价 15 (其他组合可假设代价很大,但题目一般会给出完整表格)。 问最小总代价。 二、问题分析与区间 DP 思路 这个问题是典型的“合并相邻元素”类型,与“石子合并”相似,但区别在于: 合并后产生的新字符与原来的两个字符不同。 因此最终合并得到的单个字符是什么,取决于合并顺序。 状态设计 : 定义 dp[ l][ r][ c] = 将区间 [ l, r ] 合并成一个字符 c 所需的最小代价。 如果不可能合并成 c,则为无穷大。 l, r 是字符串下标(1‑based 或 0‑based 均可),c 是字符集中的一个字符。 最终答案 : min{ dp[ 1][ n][ c ] | c ∈ Σ } 三、状态转移方程推导 区间 [ l, r] 要合并成字符 c,那么最后一次合并一定是将 [ l, k] 合并成某个字符 a,[ k+1, r ] 合并成某个字符 b,并且 nextChar(a, b) = c,合并代价为 mergeCost(a, b)。 所以: dp[ l][ r][ c ] = min{ dp[ l][ k][ a] + dp[ k+1][ r][ b ] + mergeCost(a, b) } 其中: k 从 l 到 r-1 枚举(分割点), a, b 枚举所有字符。 初始条件 : 区间长度为 1 时,dp[ l][ l][ s[ l] ] = 0(因为已经就是该字符,无需合并), 对于其他字符 ch ≠ s[ l],dp[ l][ l][ ch ] = INF(不可能变成别的字符)。 四、DP 计算顺序 因为区间长度 len 从 2 到 n 递推: 枚举起点 l,r = l+len-1。 枚举分割点 k ∈ [ l, r-1 ]。 枚举 a ∈ Σ, b ∈ Σ。 如果 dp[ l][ k][ a] 和 dp[ k+1][ r][ b ] 都不是 INF,则计算 c = nextChar(a, b), 更新 dp[ l][ r][ c] = min(dp[ l][ r][ c], dp[ l][ k][ a] + dp[ k+1][ r][ b ] + mergeCost(a, b))。 复杂度:O(n³·|Σ|³),如果 |Σ| 很小(比如 26 或更小),可以接受。 五、例子推演 假设字符集 Σ = {0, 1, 2},字符串 s = "012",规则: nextChar 表: 0+1→2, cost=5 1+2→0, cost=3 0+2→1, cost=4 (其他组合假设不可能,代价 INF) 初始: dp[ 1][ 1][ 0] = 0, dp[ 2][ 2][ 1] = 0, dp[ 3][ 3][ 2 ] = 0,其余 INF。 len=2 : 区间 [ 1,2 ]:字符 0 和 1,可合并为 2,代价 5, dp[ 1][ 2][ 2] = dp[ 1][ 1][ 0] + dp[ 2][ 2][ 1 ] + 5 = 0+0+5 = 5。 区间 [ 2,3 ]:字符 1 和 2,可合并为 0,代价 3, dp[ 2][ 3][ 0] = dp[ 2][ 2][ 1] + dp[ 3][ 3][ 2 ] + 3 = 0+0+3 = 3。 len=3 : 区间 [ 1,3 ],枚举 k=1 或 k=2。 k=1: 左边 [ 1,1]→{0},右边 [ 2,3]→{0}(但注意 [ 2,3 ] 只能变成 0,因 1+2→0), a=0, b=0,查表 0+0 无定义(假设不可合并),跳过。 左边 {0} 与右边 {0} 无法合并成 Σ 中任何字符,无更新。 k=2: 左边 [ 1,2]→{2},右边 [ 3,3 ]→{2}, a=2, b=2,2+2 无定义,跳过。 但实际上左边 [ 1,2 ] 只能变成 2,右边是字符 2,2+2 不可合并,所以不行。 但还有别的 a,b 吗?我们只存储了 [ 1,2 ] 变成 2 的可能,所以只有 a=2, b=2 这一对,不可合并。 难道无解?检查: 合并顺序1:先合并 0 1 得到 2(代价5),字符串变 "22",然后 2+2 无定义,失败。 合并顺序2:先合并 1 2 得到 0(代价3),字符串变 "00",然后 0+0 无定义,失败。 所以这个例子中,无法合并成单个字符? 说明规则表必须保证任何两个字符都能合并成某个字符(即合并是封闭的),否则可能无解。 我们修正规则,假设 0+0→0, 1+1→1, 2+2→2,代价 0。 那么: dp[ 2][ 3][ 0 ] = 3 仍成立。 现在 len=3, k=2: 左边 [ 1,2]→{2},右边 [ 3,3 ]→{2}, a=2, b=2,合并 2+2→2 代价 0, c=2, dp[ 1][ 3][ 2] = min(INF, dp[ 1][ 2][ 2] + dp[ 3][ 3][ 2 ] + 0) = 5+0+0 = 5。 k=1: 左边 [ 1,1]→{0},右边 [ 2,3 ]→{0}, 0+0→0 代价 0, dp[ 1][ 3][ 0 ] = 0 + 3 + 0 = 3。 所以最终答案是 min(dp[ 1][ 3][ 0], dp[ 1][ 3][ 2 ]) = min(3, 5) = 3。 六、总结 本题是区间 DP 的一个变体,关键点是状态中要记录合并成的字符,因为合并结果影响后续合并。 它和“石子合并”的差异在于结果字符变化,因此状态维度多了一维(字符)。 常用于模拟某些化学分子结合、符号表达式化简等问题。 如果你在题目中看到“每次合并相邻两个符号,根据规则生成新符号,并付出代价,求合并到单个符号的最小代价”,就是此类问题。