分割回文串

给你一个字符串 s,请你将s分割成一些子串,使每个子串都是回文串,返回 s 所有可能的分割方案

1. 回溯+动态规划

class Solution {
public:
    vector<vector<int>> dp;
    vector<vector<string>> res;
    vector<string> cur;
    int n;
    vector<vector<string>> partition(string s) {
        n = s.size();
        dp.assign(n, vector<int>(n, true));//dp[i][j]表示i和j之间子串是否为回文串,初始化对角线为真
        //动态规划预先计算,递推方式有很多,也可以按长度递推
        for (int i = n - 1; i >= 0; --i) //从右往左改变初始位置
            for (int j = i + 1; j < n; ++j) //改变长度
                dp[i][j] = (s[i] == s[j]) && dp[i + 1][j - 1];
        dfs(s, 0);//回溯从0位置开始
        return res;
    }
    void dfs(string& s, int i) {
    if (i == n) {//边界条件
        res.push_back(cur);
        return;
    }
    for (int j = i; j < n; ++j) {//遍历所有选择
        if (dp[i][j]) {
            cur.push_back(s.substr(i, j - i + 1));//做选择,把i~j的子串加入结果
            dfs(s, j + 1);
            cur.pop_back();//撤销选择
        }
    }
    }
};

2. 回溯 + 记忆化搜索

class Solution {
public:
    vector<vector<int>> dp;
    vector<vector<string>> res;
    vector<string> cur;
    int n;
    void dfs(string& s, int i) {
        if (i == n) {//边界条件
            res.push_back(cur);
            return;
        }
        for (int j = i; j < n; ++j) {//做选择
            if (isPalindrome(s, i, j) == 1) {
                cur.push_back(s.substr(i, j - i + 1));
                dfs(s, j + 1);
                cur.pop_back();
            }
        }
    }
    int isPalindrome(const string& s, int i, int j) {
        if (dp[i][j]) return dp[i][j];//存在直接返回
        if (i >= j)  return dp[i][j] = 1;//边界条件
        return dp[i][j] = (s[i] == s[j] ? isPalindrome(s, i + 1, j - 1) : -1);//递归
    }
    vector<vector<string>> partition(string s) {
        n = s.size();
        dp.assign(n, vector<int>(n));
        dfs(s, 0);
        return res;
    }
};
posted @ 2023-05-04 21:18  失控D大白兔  阅读(8)  评论(0编辑  收藏  举报