还是回文数,不过这题是要找出所有可能的划分方法,没有太大的难度,主要是要对细节思考细心一点。
我的解法:
依然是DP的思想,保存每一个位置的所有划分方法,每一个合法的划分是一个字符串数组vector<string> subvec, 每个位置的划分方法则是所有不同合法划分组成的数组vector<vector<string>> res,则保存所有位置的可划分的解的是各个位置的划分方法组成的数组vector<vector<vector<string>>> parvec;
DP的公式推导:首先在已知s[0..j]的所有划分情况时,j + 1的划分方法等于所有可以j + 1构成回文的位置k(k >= 0 and k <= j + 1)之前的所有划分方法和[k, j + 1]这个回文组合构成的划分,即把s[k – 1]中每一个合法的划分加上[k, j + 1]回文构成的一个新的划分作为s[j + 1]的一个合法划分,不过要注意k == 0时的情况,此时k之前的合法划分为空。
1 class Solution {
2 public:
3 vector<vector<string>> partition(string s) {
4 // Start typing your C/C++ solution below
5 // DO NOT write int main() function
6 int n = s.size();
7 vector<vector<string>> res;
8 vector<string> subvec;
9 if (n == 1) {
10 subvec.push_back(s);
11 res.push_back(subvec);
12 return res;
13 }
14 vector<vector<vector<string>>> parvec(n);
15 subvec.push_back(s.substr(0, 1));
16 res.push_back(subvec);
17 parvec[0] = res;
18 for (int i = 1; i < n; i++) {
19 for (int j = 0; j <= i; j++) {
20 if (isPalindrome(s, j, i)) {
21 string rh = s.substr(j, i - j + 1);
22 if (j == 0) {
23 vector<string> pal;
24 pal.push_back(rh);
25 parvec[i].push_back(pal);
26 }
27 else {
28 for (vector<vector<string>>::iterator it = parvec[j - 1].begin();
29 it != parvec[j - 1].end(); it++) {
30 vector<string> tmp = *it;
31 tmp.push_back(rh);
32 parvec[i].push_back(tmp);
33 }
34 }
35
36 }
37 }
38 }
39 return parvec[n - 1];
40 }
41 bool isPalindrome(string &s, int start, int end) {
42 if (start == end)
43 return true;
44 for (int i = 0; i <= (end - start) / 2; i++) {
45 if (s[start + i] != s[end - i]) {
46 return false;
47 }
48 }
49 return true;
50 }
51 };