static vector<vector<string>> partition(string s) {
    length = (int)s.size();
    table = getState(s);
    str = s;
    partitionHelper(0);
    return ret;
}
 void partitionHelper(string &s, int index, vector<vector<string>> &ans, vector<string> a) {
     if (index == s.length()) {
         // judge the a.back()
         if (isPalindrome(a.back()))
             ans.push_back(a);
     } else {
         a.back().push_back(s[index]);
         partitionHelper(s, index + 1, ans, a);
         a.back().pop_back();
         
         if (isPalindrome(a.back())) {
             a.push_back(s.substr(index, 1));
             partitionHelper(s, index + 1, ans, a);
         }
     }
 }
 vector<vector<string>> partition(string s) {
     /* https://oj.leetcode.com/problems/palindrome-partitioning/
     two steps:
     1, bool P[n][n]: figure out witch substrings of s are palindrome
     2, generate palindrome partitions according to P[n][n]
     */
     
     const int n = s.size();
     vector<vector<string> > result;
     if (n == 0) {
         result.push_back(vector<string>(1, ""));
         return result;
     }
     
     // determine with substrs are palindrome
     vector<vector<bool> > P(n, vector<bool>(n)); // P[i][j] == true iff s[i..j] is palindrome
     for (int i = 0; i < n; i++) P[i][i] = true;
     for (int i = 0; i < n - 1; i++) P[i][i+1] = s[i] == s[i+1];
     for (int len = 3; len <= n; len++) {
         for (int i = 0; i + len <= n; i++) {
             int j = i + len - 1;
             P[i][j] = P[i+1][j-1] && s[i] == s[j];
         }
     }
     
     // generate palindrome partitions
     vector<string> answer;
     partitionHelper(s, P, 0, answer, result);
     
     return result;
 }
 /**
  * @param s: A string
  * @return: A list of lists of string
  */
 vector<vector<string>> partition(string s) {
     // write your code here
     vector<vector<string> > res;
     vector<string> sol;
     int n = s.length();
     vector<vector<int> > mp(n, vector<int>(n,0)); // avoid dup caculation
     partitionHelper(s, 0, res, sol, mp);
     return res;
 }
 void partitionHelper(int st, int ed, int cnt, string tmp, string buf[]) {
     if (ed >= N) {
         int a;
         a = 1;
         if (st == ed) {
             vector <string> tmp;
             for (int i = 0; i < cnt; i++) {
                 tmp.push_back(buf[i]);
             }
             ret.push_back(tmp);
         }
         return;
     }
     tmp += S[ed];
     if (isPalindrome[st][ed]) {
         buf[cnt] = tmp;
         partitionHelper(ed + 1, ed + 1, cnt + 1, "", buf);
     }
     partitionHelper(st, ed + 1, cnt, tmp, buf);
 }
static void partitionHelper(int start){
    if (start == length) {
        ret.push_back(temp);
        return;
    }
    //Find all candidates
    for (int i = start; i < length; i++) {
        if (table[start][i]) {
            temp.push_back(str.substr(start,i-start+1));//make_move
            partitionHelper(i+1);
            temp.pop_back();//unmake_move
        }
    }
}
    void partitionHelper(string &s, int start, vector<vector<string> > &res, vector<string> &sol, vector<vector<int> > &mp){
        if(start == s.length()){
            res.push_back(sol);
            return;
        }

        for(int i=start; i<s.length(); i++){
            if(isPal(start, i, s, mp)){
               sol.push_back(s.substr(start, i-start+1));
               partitionHelper(s, i+1, res, sol, mp);
               sol.pop_back();
            }
        }
    }
 void partitionHelper(string &s, vector<vector<bool> > &P, int start, vector<string> &answer, 
     vector<vector<string> > &result) {
     
     if (start == s.size()) {
         result.push_back(answer);
         return ;
     }
     
     for (int i = start; i < s.size(); i++) {
         if (P[start][i]) {
             answer.push_back(s.substr(start, i-start+1));
             partitionHelper(s, P, i+1, answer, result);
             answer.pop_back();
         }
     }
 }
 vector<vector<string> > partition(string s) {
     S = s;
     N = s.size();
     string buf[N];
     for (int i = 0; i < N; i++) {
         for (int j = 0; j < N; j++) {
             isPalindrome[i][j] = 0;
             if (i == j || (i + 1 == j && s[i] == s[j])) {
                 isPalindrome[i][j] = true;
             }
         }
     }
     for (int i = 3; i <= N; i++) {
         for (int st = 0; st + i <= N; st++) {
             int ed = st + i -1;
             if (s[st] == s[ed] && isPalindrome[st + 1][ed - 1]) {
                 isPalindrome[st][ed] = 1;
             }
         }
     }
     partitionHelper(0, 0, 0, "", buf);
     return ret;
 }
 vector<vector<string>> partition(string s) {
     vector<vector<string>> ans;
     vector<string> a = {""};
     partitionHelper(s, 0, ans, a);
     return ans;
 }