题目描述:
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.
这道题可以用两次DP来解, 第一个二维数组palindrome[i][j]
表示s从i到j的子串是不是回文串, 第二个数组dp[i]
保存从0到i的子串有几种分割方法. 对于dp[i]
来说, 它有几种分割方法取决于以s[i]
为结尾的回文串有多少个. 由于使用普通的遍历比较方法来判断所有的回文串是一个三重循环, 而用DP+从中间向两边比较的方法可以用双重循环解决. 所以总的复杂度是O(n2).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| class Solution { public: int minCut(string s) { int len = s.length(); vector<int> dp(len + 1); vector<vector<int>> palindrome(len, vector<int>(len, 0)); for(int i = 0; i < len - 1; i++){ palindrome[i][i] = 1; if(s[i] == s[i + 1]) palindrome[i][i + 1] = 1; } palindrome[len - 1][len - 1] = 1; for(int l = 2; l < len; l++){ for(int i = 0; i + l < len; i++){ if(s[i] == s[i + l]) palindrome[i][i + l] = palindrome[i + 1][i + l - 1]; } } dp[0] = dp[1] = 0; for(int i = 2; i <= len; i++){ if(palindrome[0][i - 1]) dp[i] = 0; else{ int minCut = INT_MAX; for(int j = i - 1; j > 0 && minCut > 1; j--){ if(palindrome[j][i - 1]){ minCut = min(minCut, dp[j] + 1); } } dp[i] = minCut; } } return dp[len]; } };
|
其实可以把第二个循环的内容也放到第一个循环中去. 为了按行列的顺序来访问数组, 我把palindrome[i][j]
的含义改为从j到i的字串是否为回文串.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class Solution { public: int minCut(string s) { int len = s.length(); if(len < 2) return 0; vector<int> dp(len); vector<vector<int>> palindrome(len, vector<int>(len, 0)); for(int i = 0; i < len - 1; i++){ palindrome[i][i] = 1; if(s[i] == s[i + 1]) palindrome[i + 1][i] = 1; } palindrome[len - 1][len - 1] = 1; dp[0] = 0; dp[1] = palindrome[1][0] ? 0 : 1; for(int i = 2; i < len; i++){ int minCut = dp[i - 1] + 1; if(palindrome[i][i - 1]){ minCut = min(dp[i - 2] + 1, minCut); } for(int j = i - 2; j >= 0; j--){ if(s[j] == s[i]) palindrome[i][j] = palindrome[i - 1][j + 1]; if(j > 0 && palindrome[i][j]){ minCut = min(minCut, dp[j - 1] + 1); } } dp[i] = palindrome[i][0] ? 0 : minCut; } return dp[len - 1]; } };
|