题目链接: https://leetcode.com/problems/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.
思路:如果我们定义一个数组cut[n+1],cut[i]表示[i, n]区间有几个切点
我们要想将状态转化为子状态,那么可以从字符串右边往左扫描,逐渐增加子串长度,直到包含所有长度
那么以aabbefg为例:
0 1 2 3 4 5 6
a a b b e f g
i j n
在[i, n]区间上,如果[i, j]上子串为回文数,则可以知道如果以这种切法,cut[i] = cut[j+1] + 1, 如果这种切法比原来的cut[i]得到的切点数要少,则更新cut[i],
因此可以得到状态转移方程为:
cut[i] = min(cut[i], cut[j+1] +1)
另外还有一个需要解决的问题就是判断回文数,可以同样使用二维dp来实现
dp[i][j]表示从i到j是否为回文数,将问题转化为子状态则为:
如果s[i] == s[j],即一个子串两端相等了,则判断去掉这两端字符的子串是否为回文数,这样就把回文问题分解成了子问题,其状态转移方程为
dp[i][j] = (s[i] == s[j] && (j-i < 2 || dp[i+1][j-1]))
其中j-i < 2 意思是如果i和j相邻或者相等并且s[i]==s[j]时,则可以直接判断是回文,不需要通过子状态转化
代码如下:
class Solution { public: int minCut(string s) { int n = s.size(); if(n == 0) return 0; int cut[n+1]; bool palin[n][n]; memset(palin,false, sizeof(palin)); for(int i =0; i<= n; i++) cut[i] = n -i -1; for(int i =n-1; i >=0; i--) { for(int j = i; j< n; j++) { if(s[i] == s[j] && (j-i< 2 || palin[i+1][j-1])) { palin[i][j] = true; cut[i] = min(cut[i], cut[j+1]+1); } } } return cut[0]; } };
http://www.acmerblog.com/leetcode-solution-palindrome-partitioning-ii-6228.html