Palindrome partitioning II Total accepted: 11791 total submissions: 66110
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"]Cocould be produced using 1 cut.
This question is the deformation of palindrome partitioning. It is required to find the smallest cut so that all the substrings after cutting are input strings.
You can modify it based on palindrome partitioning and update the optimal solution when finding the feasible solution.
class Solution {public: int minCut(string s) { ans = INT_MAX; findMinCut(s, 0, 0); return ans; }private: int ans; void findMinCut(const string &s, int k, int currCut) { string substr; for (int i=k; i<s.size(); ++i) { if (isPalindrome(s, k, i)) { if (i+1 == s.size()) { if (currCut+1 < ans) { ans = currCut+1; } } else { findMinCut(s, i+1, currCut+1); } } } } bool isPalindrome(const string &s, int b, int e) { int i=b, j=e; while (i<j) { if (s[i] != s[j]) return false; ++i; --j; } return true; }};
If you increase the Memory search + pruning, it will still use TLE. The case of timeout is a large string of "aaaa... AA.
class Solution {public: int minCut(string s) { minCutNum = INT_MAX; vector<string> paths; find(s, 0, paths); return minCutNum; }private: int minCutNum; map<int, int> minCutsMap; void find(const string& s, int ind, vector<string>& paths) { for (int i = ind; i < s.size(); ++i) { if (isPalindrome(s, ind, i)) { if (paths.size() > minCutNum) continue; if (minCutsMap.find(i+1) != minCutsMap.end()) { if (paths.size() + minCutsMap.size() - 1 < minCutNum) { minCutNum = paths.size() + minCutsMap.size() - 1; } continue; } paths.push_back(s.substr(ind, i - ind + 1)); if (i + 1 == s.size()) { if (minCutNum > paths.size() - 1) { minCutNum = paths.size() - 1; } paths.pop_back(); continue; } int num = paths.size(); minCutsMap[i + 1] = INT_MAX; find(s, i + 1, paths); if (minCutsMap[i + 1] > paths.size() - num) { minCutsMap[i + 1] = paths.size() - num; } if (minCutNum == 0) return; paths.pop_back(); } } } bool isPalindrome(const string& str, int begin, int end) { while (begin < end) { if (str[begin] != str[end]) return false; ++begin; --end; } return true; }};
Finally, I made a reference to someone else's DP on the internet, wrote it myself, and finally saw the accepted. The method for initializing ispalindrome also uses the DP method, which is similar to the calculation of the smallest number of matrix concatenation operations. Assume that the string is STR and the length is N. The state transition equation for calculating the minimum cut count is: DP [I] = min {DP [J] + 1, DP [I]} (j = I + 1... n-1), where DP [I] is str [I]... the minimum number of splits for STR [n-1. When doing the DP question, you should consider how to save the status and how the status is transferred. The advantage of DP is that it can make the current optimal choice based on the previous choice, such as greedy algorithm, and only the local optimal state in the past.
class Solution {public: int minCut(string s) { int len = s.size(); bool **isPalindrome = new bool*[len]; for (int i = 0; i < len; ++i) { isPalindrome[i] = new bool[len]; } initIsPalindrome(isPalindrome, s); int *dp = new int[len]; // dp[i] stores minimum cuts for s[i]...s[len-1] for (int i = len - 1; i >= 0; --i) { if (isPalindrome[i][len - 1]) { dp[i] = 0; continue; } dp[i] = INT_MAX; for (int j = i + 1; j < len; ++j) { if (isPalindrome[i][j - 1]) { if (dp[j] + 1 < dp[i]) { dp[i] = dp[j] + 1; } } } } int ret = dp[0]; for (int i = 0; i < len; ++i) delete []isPalindrome[i]; delete []isPalindrome; delete dp; return ret; }private: void initIsPalindrome(bool ** isPalindrome, const string& s) { int len = s.length(); for (int L = 1; L <= len; ++L) { // L is the length of substring, from 1 to len for (int i = 0; i < len - L + 1; ++i) { // i is the starting index int j = i + L - 1; // j is the ending index if (L == 1) { isPalindrome[i][j] = true; } else if (L == 2) { isPalindrome[i][j] = s[i] == s[j]; } else { isPalindrome[i][j] = (s[i] == s[j]) && isPalindrome[i + 1][j - 1]; } } } }};