区间动态规划例题:最小插入次数构造回文串问题(进阶版)
字数 1477 2025-11-02 10:11:13
区间动态规划例题:最小插入次数构造回文串问题(进阶版)
题目描述
给定一个字符串 s,你可以在任意位置插入任意字符,每次插入操作记为一次成本。要求计算出使字符串成为回文串所需的最小插入次数。与基础版不同,进阶版中允许插入的字符可以是任意字符,但目标是最小化总插入次数。例如,对于字符串 "abca",最小插入次数为 1(在末尾插入 'a' 得到 "abcba")。
解题过程
-
问题分析
回文串的特点是正读反读相同。若字符串s本身不是回文,需要通过插入字符使其对称。关键观察是:最小插入次数等于字符串长度减去其最长回文子序列(LPS)的长度。因为保留最长回文子序列后,只需为剩余字符插入对称字符即可。 -
定义状态
设dp[i][j]表示子串s[i:j+1]变成回文串所需的最小插入次数。目标是求dp[0][n-1],其中n为字符串长度。 -
状态转移方程
- 如果
s[i] == s[j],则两端字符已匹配,直接考虑内部子串s[i+1:j]的插入次数:
dp[i][j] = dp[i+1][j-1](当j > i+1时)
注意:当j == i+1时,两字符相邻且相等,无需插入,dp[i][j] = 0;当j == i时,单字符已是回文,dp[i][j] = 0。 - 如果
s[i] != s[j],则需在左侧或右侧插入字符匹配另一端:- 在右侧插入
s[i]匹配左端:成本为1 + dp[i+1][j](即忽略s[i],先处理s[i+1:j+1])。 - 在左侧插入
s[j]匹配右端:成本为1 + dp[i][j-1](即忽略s[j],先处理s[i:j])。
取最小值:dp[i][j] = min(dp[i+1][j], dp[i][j-1]) + 1。
- 在右侧插入
- 如果
-
初始化与遍历顺序
- 初始化:单个字符无需插入,即
dp[i][i] = 0。 - 遍历顺序:由于
dp[i][j]依赖左下方(i+1)、左侧(j-1)的值,需按区间长度len从小到大的顺序计算(len从 2 到n)。
- 初始化:单个字符无需插入,即
-
示例计算
以s = "abca"为例(n=4):- 初始化:所有
dp[i][i] = 0。 - 长度 2:
dp[0][1]:'a' != 'b',min(dp[1][1], dp[0][0]) + 1 = min(0,0) + 1 = 1。dp[1][2]:'b' != 'c',min(dp[2][2], dp[1][1]) + 1 = 1。dp[2][3]:'c' != 'a',min(dp[3][3], dp[2][2]) + 1 = 1。
- 长度 3:
dp[0][2]:'a' != 'c',min(dp[1][2], dp[0][1]) + 1 = min(1,1) + 1 = 2。dp[1][3]:'b' != 'a',min(dp[2][3], dp[1][2]) + 1 = min(1,1) + 1 = 2。
- 长度 4:
dp[0][3]:'a' == 'a',匹配两端,内部子串dp[1][2] = 1,所以dp[0][3] = 1。
最终结果为dp[0][3] = 1,与直观解法一致。
- 初始化:所有
-
复杂度分析
时间复杂度 O(n²),空间复杂度 O(n²)(可优化至 O(n))。