Timeline
Timeline
2026-03-16
init
Dynamic programming + backtracking
Problem:
Backtracking: find combinations of partition sizes such that each substring is a palindrome
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 | using std::vector;using std::string;class Solution { private: void __partition(string &s, vector<vector<int> > &sum_vec, vector<int> &curr, int curr_sum) { int i, n = s.size(); if (curr_sum == n) { sum_vec.push_back(curr); return; } for (i = 1; i <= n; i++) { if (curr_sum + i <= n && isPalindrome(s.substr(curr_sum, i))) { curr.push_back(i); __partition(s, sum_vec, curr, curr_sum + i); curr.pop_back(); } } } bool isPalindrome(string s) { int left = 0, right = s.size() - 1; while (left < right) { if (s[left] != s[right]) return false; left++; right--; } return true; } public: vector<vector<string> > partition(string s) { int pos, n = s.size(); bool flag = false; vector<vector<string> > ret; vector<vector<int> > sum_vec; vector<int> curr; __partition(s, sum_vec, curr, 0); for (vector<int> &combinatioin : sum_vec) { vector<string> curr_str_vec; pos = 0; for (int size : combinatioin) { curr_str_vec.push_back(s.substr(pos, size)); pos += size; } ret.push_back(curr_str_vec); } return ret; }}; |
However, the above method of checking palindromes involves a lot of repeated computation, so consider dynamic programming.
We can precompute whether each substring s[i…j] of string s is a palindrome using dynamic programming. Let f(i,j) denote whether s[i…j] is a palindrome, then we have the state transition equation:
After optimization:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465 | using std::vector;using std::string;class Solution { private: void __partition(string &s, vector<vector<int> > &sum_vec, vector<int> &curr, int curr_sum, vector<vector<bool> > &isPalindrome) { int i, n = s.size(); if (curr_sum == n) { sum_vec.push_back(curr); return; } for (i = 1; i <= n; i++) { if (curr_sum + i <= n && isPalindrome[curr_sum][curr_sum + i - 1]) { curr.push_back(i); __partition(s, sum_vec, curr, curr_sum + i, isPalindrome); curr.pop_back(); } } } public: vector<vector<string> > partition(string s) { int pos, n = s.size(); vector<vector<string> > ret; vector<vector<int> > sum_vec; vector<int> curr; vector<vector<bool> > isPalindrome(n, vector<bool>(n, false)); for (int i = n - 1; i >= 0; i--) { for (int j = i; j < n; j++) { if (s[i] == s[j]) { if (j - i <= 2) isPalindrome[i][j] = true; else isPalindrome[i][j] = isPalindrome[i + 1][j - 1]; } } } __partition(s, sum_vec, curr, 0, isPalindrome); for (vector<int> &combinatioin : sum_vec) { vector<string> curr_str_vec; pos = 0; for (int size : combinatioin) { curr_str_vec.push_back(s.substr(pos, size)); pos += size; } ret.push_back(curr_str_vec); } return ret; }}; |
Official solution
123456789101112131415161718192021222324252627282930313233343536 | class Solution {private: vector<vector<int>> f; vector<vector<string>> ret; vector<string> ans; int n;public: void dfs(const string& s, int i) { if (i == n) { ret.push_back(ans); return; } for (int j = i; j < n; ++j) { if (f[i][j]) { ans.push_back(s.substr(i, j - i + 1)); dfs(s, j + 1); ans.pop_back(); } } } vector<vector<string>> partition(string s) { n = s.size(); f.assign(n, vector<int>(n, true)); for (int i = n - 1; i >= 0; --i) { for (int j = i + 1; j < n; ++j) { f[i][j] = (s[i] == s[j]) && f[i + 1][j - 1]; } } dfs(s, 0); return ret; }}; |
