Description
Given a string s, partition s such that every substring of the partition is a palindrome.
Return the minimum cuts needed for a palindrome partitioning of s.
For example, givens = "aab"
,
Return 1
since the palindrome partitioning["aa","b"]
could be produced using 1 cut.
Solution
暴力枚举费时,不好下手,很难达到全局最优,这里我们用DP:
设dp[i]
为字符串s
的前i
个字符的最少切分次数,那么有:
dp[i]
初始值为i
,表示前i
个字符最多需要切分i
次- 转移方程为
dp[i] = min(dp[i], dp[j-1]+1)
,其中0<=j<i
,s[i] == s[j]
,s[i+1]...s[j-1]
为回文串
需要注意两个问题:
- 每次更新
dp[i]
都需要从新计算回文串,可以用数组保存回文串状态,记isPalin[i][j]
为s[i]...s[j]
是回文串 - 如果从左到右扫描需要处理左边界,为了编程方便,我们可以从右到左处理,
dp[n] = -1
,这样转移方程变为dp[i] = min(dp[i], dp[j+1] + 1)
,表示从s[i]
和s[j]
处切分字符串的最少次数
Code
class Solution {
public:
int minCut(string s) {
int n = s.length();
vector<vector<bool>> isPalin(n, vector<bool>(n, false));
vector<int> dp(n+1, -1);
for (int i=0; i<n; i++)
isPalin[i][i] = true;
for (int i=n-1; i>=0; i--) {
dp[i] = dp[i+1] + 1;
for (int j=i+1; j<n; j++) {
if (s[i] == s[j]) {
if (j == i+1 || isPalin[i+1][j-1]) {
isPalin[i][j] = true;
dp[i] = min(dp[i], dp[j+1] + 1);
}
}
}
}
return dp[0];
}
};