最长回文子串分割的最小切割次数问题(进阶版:带权值)
题目描述
给定一个字符串s,长度为n,每个字符s[i]有一个正整数的权值w[i]。要求将s分割成若干个子串,使得每个子串都是回文串,并且所有回文子串的权值之和最小。这里的权值之和定义为:每个回文子串的权值等于其最重字符的权值(即该子串中所有字符权值的最大值),而总权值是所有回文子串权值之和。求最小的总权值。
例如,字符串s = "aba",权值数组w = [2, 3, 2],一种分割方式是["a", "b", "a"],总权值为max(2) + max(3) + max(2) = 2 + 3 + 2 = 7;另一种分割方式是["aba"],总权值为max(2,3,2) = 3。最小总权值为3。
解题过程
-
问题分析
这是一个区间动态规划问题,需要找到字符串的最优回文分割方案。与基础的回文分割问题不同,这里每个回文子串的权值不是简单的长度或固定成本,而是子串内字符权值的最大值,这增加了状态转移的复杂性。 -
定义状态
设dp[i]表示字符串前i个字符(s[0:i])的最小总权值。目标是求dp[n]。 -
状态转移方程
考虑最后一个回文子串s[j:i](0 ≤ j < i),如果s[j:i]是回文串,那么:
dp[i] = min(dp[i], dp[j] + max_weight(j, i-1))
其中max_weight(j, i-1)表示子串s[j:i]中字符权值的最大值。为了高效计算任意子串s[j:i]是否为回文串,可以预处理一个二维数组is_palindrome,其中is_palindrome[j][i]表示s[j:i]是否为回文串。
-
预处理回文信息
使用动态规划预处理is_palindrome:- 初始化:所有长度为1的子串都是回文串;长度为2的子串若两字符相同则是回文串。
- 对于长度大于2的子串s[j:i],若s[j] == s[i-1]且is_palindrome[j+1][i-1]为真,则s[j:i]是回文串。
-
预处理区间最大值
为了快速计算max_weight(j, i-1),可以预处理一个二维数组max_w,其中max_w[j][i]表示子串s[j:i]的权值最大值。这可以通过动态规划或直接遍历计算。 -
算法步骤
- 预处理is_palindrome和max_w数组。
- 初始化dp[0] = 0(空字符串权值为0)。
- 对于i从1到n,遍历j从0到i-1:
如果is_palindrome[j][i]为真,则更新dp[i] = min(dp[i], dp[j] + max_w[j][i])。 - 返回dp[n]。
-
复杂度分析
预处理is_palindrome和max_w需要O(n²)时间,主动态规划过程也需要O(n²)时间,总时间复杂度为O(n²)。空间复杂度为O(n²)。
示例验证
以s = "aba", w = [2,3,2]为例:
- 预处理is_palindrome:
is_palindrome[0][1] = True("a"),is_palindrome[1][2] = True("b"),is_palindrome[2][3] = True("a"),
is_palindrome[0][2] = False("ab"),is_palindrome[1][3] = False("ba"),is_palindrome[0][3] = True("aba")。 - 预处理max_w:
max_w[0][1]=2, max_w[1][2]=3, max_w[2][3]=2,
max_w[0][2]=max(2,3)=3, max_w[1][3]=max(3,2)=3, max_w[0][3]=max(2,3,2)=3。 - 计算dp:
dp[0]=0,
dp[1]=dp[0]+max_w[0][1]=0+2=2,
dp[2]=min(dp[0]+max_w[0][2]=0+3=3, dp[1]+max_w[1][2]=2+3=5) = 3,
dp[3]=min(dp[0]+max_w[0][3]=0+3=3, dp[1]+max_w[1][3]=2+3=5, dp[2]+max_w[2][3]=3+2=5) = 3。
最小总权值为3,符合预期。
通过以上步骤,可以解决带权值的最优回文分割问题。