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.
For example, given s = "aab"
,
Return 1
since the palindrome partitioning ["aa","b"]
could be produced using 1 cut.
解题思路:先求出所有可能的回文串一次动态规划,然后在此基础上二次用动态规划求出最小分割次数
比较类似矩阵连乘问题,但是O(n^3)的复杂度会导致超时。
解法一超时
class Solution {
public:
//判断字符串s [b,e]是不是回文
bool isPalindrome(string &s, size_t b, size_t e){
while(b < e){
if(s[b] != s[e]) return false;
b++; e--;
}
return true;
}
int minCut(string s) {
size_t n = s.size();
vector<vector<bool> > vvi(n, vector<bool>(n, false));
//动态规划 vvi[i, j]表示从i到j是回文串 此处的时间复杂度O(n^3)所以超果
for(int i = 0; i < n; i++){
for(int j = i; j < n; j++){
vvi[i][j] = isPalindrome(s, i, j); //这里需要优化
}
}
vector<int> vi(n, 0);
//二次动态规划
for(int i = 1; i < n; i++){
if(vvi[0][i]){
continue; //如果是回文串直接跳过
}
int tmpn = n;
//找出以j为分割点的所有最小划分
for(int j = 0; j < i; j++){
if(vvi[j + 1][i]){
tmpn = min(tmpn, vi[j] + 1); //如果vvi[j+1][i]是回文串
}else{//如果不是
tmpn = min(tmpn, vi[j] + i - j);
}
}
vi[i] = tmpn;
}
return vi[n - 1];
}
};
针对解法一中需要优化的地方,要对求回文串也使用动态规划的方法
dp[i][j]表示从i到j的字符,包括i,j是回文串,如图所示
dp[i][j] = true; if(s[i] == s[j] && j - i < 2)
dp[i][j] = true; if(s[i] == s[j] && dp[i + 1][j - 1])
第二个表达式是一种递归的定义,如果s[i] s[j]相等,那么s[i + 1] 至s[j - 1]如果是回文即dp[i + 1][j - 1]为真则dp[i+1][j-1]为真
而对于最小切分也是一种动态规划
v[i]表示从0到i的最小切分次数
v[i] = min(v[k] + 1/* 0<= k < i, s[k + 1]至s[i]是回文串*/, v[k] + i - k/*s[k+1] 至s[i]不是回文串*/)
class Solution {
public:
int minCut(string s) {
size_t n = s.size();
vector<vector<bool> > vvi(n, vector<bool>(n, false));
//动态规划 vvi[i, j]表示从i到j是回文串
for(int i = n - 1; i >= 0; i--){
for(int j = i; j < n; j++){
if(s[i] == s[j] &&(j - i < 2 || vvi[i + 1][j - 1])){
vvi[i][j] = true;
}
}
}
vector<int> vi(n, 0);
for(int i = 1; i < n; i++){ //动态规划找最小划分次数
if(vvi[0][i]){
continue; //如果是回文串直接跳过
}
int tmpn = n;
//找出以j为分割点的所有最小划分
for(int j = 0; j < i; j++){
if(vvi[j + 1][i]){
tmpn = min(tmpn, vi[j] + 1); //如果vvi[j+1][i]是回文串
}else{//如果不是
tmpn = min(tmpn, vi[j] + i - j);
}
}
vi[i] = tmpn;
}
return vi[n - 1];
}
};