132. 分割回文串 II(两次dp)
给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文。
返回符合要求的 最少分割次数 。
示例 1:
输入:s = "aab"
输出:1
解释:只需一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。
示例 2:
输入:s = "a"
输出:0
示例 3:
输入:s = "ab"
输出:1
先从分割回文串I 的方法预处理求出所有回文串。
for(int i = n - 1; i >= 0; i--){ for(int j = i + 1; j < n; j++){ f[i][j] = f[i + 1][j - 1] && s[i] == s[j]; } }
递推「最小分割次数」思路
我们定义 f[i] 为以下标为 i 的字符作为结尾的最小分割次数,那么最终答案为 f[n - 1]。
不失一般性的考虑第 j 字符的分割方案:
1.从起点字符到第 j 个字符能形成回文串,那么最小分割次数为 0。此时有 f[j] = 0
2.从起点字符到第 j 个字符不能形成回文串:
1.该字符独立消耗一次分割次数。此时有 f[j] = f[j - 1] + 1
2.该字符不独立消耗一次分割次数,而是与前面的某个位置 i 形成回文串,[i, j] 作为整体消耗一次分割次数。此时有 f[j] = f[i - 1] + 1
在 2.2 中满足回文要求的位置 i 可能有很多,我们在所有方案中取一个 min 即可。
class Solution { public: vector<vector<bool>> f; int minCut(string s) { int n = s.size(); f.assign(n,vector<bool>(n,true)); vector<int> dp(n,INT_MAX); // f[i][j] = (f[i + 1][j - 1] && s[i] == s[j]) // 预处理 for(int i = n - 1; i >= 0; i--){ for(int j = i + 1; j < n; j++){ f[i][j] = f[i + 1][j - 1] && s[i] == s[j]; } } for(int i = 0; i < n; i++){ if(f[0][i]){ dp[i] = 0; continue; } for(int j = 0; j < i; j++){ if(f[j + 1][i]) dp[i] = min(dp[i],dp[j] + 1); } } return dp[n - 1]; } };
浙公网安备 33010602011771号