

横向表示从某个下标开始不断截取不同长度的字符串,直到将字符串截取完
纵向是当前截取了当前字符串后,继续截取剩余字符串
从根节点到叶子节点的路径,就组成了分割结果
class Solution {
public:
    vector<vector<string>> ans;
    vector<string> path;
    bool isPalindrome(string s){
        int l = 0;
        int r = s.size() - 1;
        while(l < r){
            if(s[l] != s[r]){
                return false;
            }
            l++;
            r--;
        }
        return true;
    }
    void func(int startIndex, const string& s){
        if(startIndex == s.size()){
            ans.push_back(path);
        }
        // n表示截取的长度
        // for循环横向遍历,从startIndex开始,不断截取,直到讲s截取完
        for(int n = 1; n <= s.size() - startIndex; n++){
            string subs = s.substr(startIndex, n);
            if(!isPalindrome(subs)){
                continue;
            }
            path.push_back(subs);
            func(startIndex + n, s);  // 截取了多少个字符,起始的下标就后移多少
            path.pop_back();        
        }
    }
    vector<vector<string>> partition(string s) {
        func(0, s);
        return ans;
    }
};算法优化:先用dp算出所有子串是否是回文串,就不用频繁调用函数判断当前子串是否是回文串了
class Solution {
public:
    vector<vector<string>> ans;
    vector<string> path;
    void func(int startIndex, const string& s, const vector<vector<bool>>& isPalindrome){
        if(startIndex == s.size()){
            ans.push_back(path);
        }
        // n表示截取的长度
        // for循环横向遍历,从startIndex开始,不断截取,直到讲s截取完
        for(int n = 1; n <= s.size() - startIndex; n++){
            string subs = s.substr(startIndex, n);
            if(!isPalindrome[startIndex][startIndex + n - 1]){
                continue;
            }
            path.push_back(subs);
            func(startIndex + n, s, isPalindrome);  // 截取了多少个字符,起始的下标就后移多少
            path.pop_back();        
        }
    }
    vector<vector<string>> partition(string s) {
        int len = s.size();
        vector<vector<bool>> isPalindrome(len, vector<bool>(len, false));
        
        for(int r = 0; r < len; r++){
            for(int l = 0; l <= r; l++){
                // 在两端字符相同的情况下,若中间间隔字符不超过1个,那就是回文串了
                // 在两端字符相同的情况下,若中间间隔字符超过1个,还需要判断内侧字符是否是回文串
                if(s[l] == s[r] && (r - l <= 2 || isPalindrome[l+1][r-1])){
                    isPalindrome[l][r] = true;
                }
            }
        }
        func(0, s, isPalindrome);
        return ans;
    }
};                










