问题: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.
与之的类似问题是《回文子串划分 Palindrome Partitioning》。
思路:两次动态规划。
第一次DP,找到字符串的任意子串是否是回文,状态量H[i][j]记录子串s[i..j]是否是回文。
其递推关系,可参考http://blog.csdn.net/ojshilu/article/details/12155529
第二次DP,找到任意前缀子串的最小回文分割数,状态量P[i]记录前缀子串s[0..i]的最小分割数。
其递推关系,若H[0][i] = 1,那么P[i] = 0,否则 P[i] = min{P[k] +1 when H[k+1][i] = 1}。
class Solution {
public:
int minCut(string s) {
int n = s.size();
if(n < 2)
return 0;
//第一次动态规划:找出任意子串是否是回文
int **H = new int *[n]; // H[i][j]表示str[i..j]是否是回文
for(int i=0;i<n;i++)
{
H[i] = new int[n];
memset(H[i], 0, sizeof(H[i]));
}
for(int i=0;i<n;i++)
H[i][i] = 1;
for(int i=0;i<n-1;i++)
if(s[i] == s[i+1])
H[i][i+1] = 1;
else
H[i][i+1] = 0;
for(int m=3;m<=n;m++)
{
for(int i=0;i<n-m+1;i++)
{
int j = i + m - 1;
if(s[i] == s[j] && H[i+1][j-1] == 1)
H[i][j] = 1;
else
H[i][j] = 0;
}
}
if(H[0][n-1] == 1)
return 0;
//第二次动态规划:找出所有前缀子串的最小分割数
int P[n]; //P[i]表示str[0..i]的最小分割数
memset(P, 0, sizeof(P));
P[0] = 0;
for(int i=1;i<n;i++)
{
if(H[0][i] == 1)
{
P[i] = 0;
continue;
}
int min = P[i-1] + 1;
for(int j=i-1;j>0;j--)
{
if(H[j][i] == 1 && P[j-1] + 1 < min)
min = P[j-1] + 1;
}
P[i] = min;
}
return P[n-1];
}
};