合并相邻字符的最小成本问题(相邻字符可合并为指定新字符,带权值)
一、题目描述
给你一个长度为 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 的一个变体,关键点是状态中要记录合并成的字符,因为合并结果影响后续合并。
它和“石子合并”的差异在于结果字符变化,因此状态维度多了一维(字符)。
常用于模拟某些化学分子结合、符号表达式化简等问题。
如果你在题目中看到“每次合并相邻两个符号,根据规则生成新符号,并付出代价,求合并到单个符号的最小代价”,就是此类问题。