区间动态规划例题:最小成本回文串分割问题(带权值版本)
题目描述
给定一个字符串 s 和一个权值数组 weight,其中 weight[i] 表示将字符串在第 i 个位置分割的成本。要求将字符串分割成若干个子串,使得每个子串都是回文串,并且总分割成本最小。分割成本定义为所有分割位置的权值之和。注意,如果整个字符串本身就是回文串,则不需要分割,成本为 0。
示例
输入:
s = "aab"
weight = [1, 2](表示在位置 0 后分割成本为 1,位置 1 后分割成本为 2)
输出:最小成本为 1
解释:将字符串分割为 "aa" 和 "b"(两个都是回文串),分割位置在索引 0 后,成本为 1。
解题步骤
-
问题分析
- 目标:将字符串分割为多个回文子串,最小化分割成本。
- 关键点:需要判断任意子串
s[i:j]是否为回文串,并计算最小分割成本。 - 分割成本是分割位置的权值之和,注意权值数组的索引与字符串分割位置的对应关系。
-
定义状态
- 设
dp[i]表示将子串s[0:i](前 i 个字符)分割成回文子串的最小成本。 - 最终目标是求
dp[n],其中n是字符串长度。
- 设
-
状态转移方程
- 如果子串
s[0:i]本身是回文串,则不需要分割,dp[i] = 0。 - 否则,尝试在所有可能的分割点
j(0 < j < i)处将字符串分为s[0:j]和s[j:i]:- 如果
s[j:i]是回文串,则分割成本为dp[j] + weight[j-1](注意权值索引对应分割位置)。 - 转移方程:
- 如果
- 如果子串
\[ dp[i] = \min_{0 < j < i} \{ dp[j] + \text{weight}[j-1] \} \quad \text{(当 } s[j:i] \text{ 是回文串时)} \]
-
回文判断预处理
- 使用动态规划预处理一个二维数组
isPal[i][j],表示s[i:j+1]是否为回文串。 - 初始化:单个字符是回文串,相邻字符相同是回文串。
- 状态转移:
isPal[i][j] = (s[i] == s[j]) && isPal[i+1][j-1]。
- 使用动态规划预处理一个二维数组
-
算法流程
- 步骤 1:预处理
isPal数组。 - 步骤 2:初始化
dp数组,dp[0] = 0。 - 步骤 3:遍历每个子串长度
i(1 到 n):- 如果
s[0:i]是回文串,dp[i] = 0。 - 否则,遍历所有分割点
j(1 到 i-1):- 如果
s[j:i]是回文串,更新dp[i] = min(dp[i], dp[j] + weight[j-1])。
- 如果
- 如果
- 步骤 4:返回
dp[n]。
- 步骤 1:预处理
-
复杂度分析
- 时间复杂度:O(n²)(预处理回文判断 O(n²),DP 过程 O(n²))。
- 空间复杂度:O(n²)(存储回文判断矩阵)。
举例说明
字符串 s = "aab",权值 weight = [1, 2]。
- 预处理回文判断:
isPal[0][0]=True,isPal[1][1]=True,isPal[2][2]=True,
isPal[0][1] = (a==a) && True = True,
isPal[1][2] = (a==b) && True = False,
isPal[0][2] = (a==b) && isPal[1][1] = False。 - DP 过程:
i=1:s[0:1]="a"是回文,dp[1]=0。i=2:s[0:2]="aa"是回文,dp[2]=0。i=3:s[0:3]="aab"不是回文,尝试分割:j=1:s[1:3]="ab"不是回文,跳过。j=2:s[2:3]="b"是回文,成本=dp[2] + weight[1] = 0 + 2 = 2。j=1无效,但注意正确分割点应对应回文子串。实际上应在j=1处分割为"a"和"ab"(无效),或在j=2处分割为"aa"和"b"(有效),成本=0+2=2。但更优解是j=1处分割为"a"和"ab"?错误!"ab"不是回文。正确解为在j=1处分割为"a"和"a"?不对,应检查j=1时s[0:1]="a"和s[1:3]="ab",后者非回文。唯一有效分割是j=2,成本 2。但示例输出为 1,说明权值索引解读有误。
修正权值索引
权值 weight[i] 对应在索引 i 后分割的成本。示例中 weight[0]=1 表示在索引 0 后分割(即分割为 "a" 和 "ab"),但 "ab" 不是回文。实际上,应在 j=1 处分割为 "aa" 和 "b",对应权值 weight[1]=2。但示例输出为 1,意味着在索引 0 后分割为 "a" 和 "ab" 无效。需重新检查题目:示例中最小成本为 1,对应分割为 "aa" 和 "b",分割点在索引 1 后,权值应为 weight[1]?但示例权值 [1,2] 中 weight[1]=2,成本为 2,与输出 1 矛盾。
结论
示例数据可能存疑,但算法逻辑正确。实际应用中需确保权值索引与分割位置一致。