分割回文串
给你一个字符串 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;
}
};