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”,
Return1since the palindrome partitioning[“aa”,”b”]could be produced using 1 cut.
这个题目可以利用动态规划解决问题,可以将复杂度降到O(n^2),首先可以利用在O(n^2)的时间内计算出所有的字符串下标从i到j是否为回文字符串.利用dp[i][j]的数组进行存储.这样之后可以在O(1)的时间复杂度判断子串i到j是否为回文字符串.
设数组mincut[i]存放的是从0到i的最小切割次数.对于mincut[j]若dp[i][j]为回文字符串则最小切割次数为mincut[i-1]+1;i的范围为从0到j.从中取出最小值.这个比较难理解,对于任意的i如果i到j为回文字符那么切割次数为mincut[i-1]+1;如果i和j不是回文字符串,则切割次数为mincut[i-1]+i和j之间切割的次数,这个一定是大于等于,i和j一定可以分解成若干回文字符串,之后又回到之前的问题组合的切割次数.这个很难理解,和剪气球串问题很像.
class Solution {
public:
int minCut(string s) {
int len=s.size();
if(len<=1)
return 0;
vector<vector<int>>* dp=new vector<vector<int>> (len,vector<int>(len,0));
for(int i=0;i<len;++i)
{
(*dp)[i][i]=1;
if(i<len-1&&s[i]==s[i+1])
(*dp)[i][i+1]=1;
}
for (int i = 0; i<len; ++i)
{
for (int j = 1; j<len; ++j) //按照斜的方式计算i到j是否是回文字符串.知道i到j就知道i-1到j+1;
{
if (j + i+1<len && (*dp)[j][j+i] == 1 && s[j-1] == s[j+i+1])
(*dp)[j - 1][j + i+1] = 1;
}
}
int* mincut=new int[len];
memset(mincut,-1,len*sizeof(mincut[0]));
for(int i=0;i<len;++i)
{
if((*dp)[0][i]==1)
mincut[i]=0;
}
for(int i=1;i<len;++i)
{
int temp=len;
if(mincut[i]==-1)
{
for(int j=i;j>=1;--j)
{
if( (*dp)[j][i]==1&&mincut[j-1]+1<temp)
temp=mincut[j-1]+1;
}
mincut[i]=temp;
}
}
int res=mincut[len-1];
delete dp;
delete[] mincut;
return res;
}
};