LeetCode:132. Palindrome Partitioning II
题目是这样:
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.
例子:
Input: “aab”
Output: 1
Explanation: The palindrome partitioning [“aa”,“b”] could be produced using 1 cut.
题目大意就是给一个字符串,问最少对它切割几次,使得到的每个子串都是回文子串。
这题明显得用动态规划。难点依然在于如何定义状态。
这题的状态定义比较特殊,需要定义两个状态,且第二个状态依赖于第一个状态求解:
pal[i][j]:表示s[i…j]能否形成回文子串。
d[i]:表示对于s[i…,n-1]的minCut。(因为这题是对于整体的问题,所以固定住一边比较好)
状态转移方程是:
pal[i][j]=true, 如果 s[i] == s[j] && (j-i<2 || pal[i+1][j-1])
当pal[i][j] ==true:
如果 j=n-1,d[i] = 0;否则,d[i] = min(1+d[j+1],n-1-i)
代码是:
class Solution {
public:
int minCut(string s) {
if (s.empty())
return 0;
int n = s.length();
vector<vector<bool>> pal(n, vector<bool>(n, false));
vector<int> d(n, 0);
for (int i = n-1; i >= 0; --i){
d[i] = n-1-i;
for (int j = i; j < n; ++j) {
if (s[i] == s[j] && (j-i<2 || pal[i+1][j-1])) {//测试是否是回文的聪明方法,不是笨方法
pal[i][j] = true;
if (j == n-1)
d[i] = 0;
else if(d[i] > d[j+1]+1)
d[i] = d[j+1]+1;
}
}
}
return d[0];
}
};
同样的状态定义,但是转移方程好像更容易理解一些:
class Solution {
public:
int minCut(string s) {
int sz = s.size();
if (sz <= 1)
return 0;
vector<vector<bool>> dp(sz, vector<bool>(sz, false));
for (int i = sz-1; i >= 0; --i)
for (int j = i; j < sz; ++j) {
if (s[i] == s[j] && (j - i <= 2 || dp[i+1][j-1]))
dp[i][j] = true;
}
vector<int> dp2(sz, INT_MAX);
dp2[0] = 0;
for (int i = 1; i < sz; ++i) {
if (dp[0][i])
dp2[i] = 0;
else {
for (int k = 1; k <= i; ++k)
if (dp[k][i])
dp2[i] = min(dp2[i], dp2[k-1]+1);
}
}
return dp2.back();
}
};
浙公网安备 33010602011771号