分割回文串
- 题解1 回溯
- 题解2 回溯+dp
- 利用dp相当于先判断哪段是回文(省掉了每次都需要调用的isValid)【预处理】
给你一个字符串
s
,请你将
s
分割成一些子串,使
每个子串都是
回文串 。返回 s 所有可能的分割方案。
回文串 是正着读和反着读都一样的字符串。
示例 1:
输入:s = "aab"
输出:[[“a”,“a”,“b”],[“aa”,“b”]]
示例 2:
输入:s = "a"
输出:[[“a”]]
提示:
- 1 <=
s.length
<= 16 s
仅由小写英文字母组成
题解1 回溯
class Solution {
vector<vector<string>> res;
vector<string> ret;
public:
// 小工具
bool isValid(string t, int lo, int hi){
while(lo < hi){
if(t[lo] != t[hi])
return false;
lo ++;
hi --;
}
return true;
}
// idx是每个子串的起点
void backtrace(string& s, int idx){
if(idx == s.size()){
res.push_back(ret);
}
// i决定了每个回文子串的长度
for(int i = idx; i < s.size(); i++){
if(! isValid(s, idx, i))
continue;
// 含i,所以+1
ret.push_back(s.substr(idx, i-idx+1));
// 加入该串的情况
backtrace(s, i+1);
// 撤回
ret.pop_back();
}
}
vector<vector<string>> partition(string s) {
backtrace(s, 0);
return res;
}
};
题解2 回溯+dp
利用dp相当于先判断哪段是回文(省掉了每次都需要调用的isValid)【预处理】
class Solution {
vector<vector<string>> res;
vector<vector<int>> dp;
vector<string> ret;
public:
// idx是每个子串的起点
void backtrace(string& s, int idx){
if(idx == s.size()){
res.push_back(ret);
return;
}
// i决定了每个回文子串的长度
for(int i = idx; i < s.size(); i++){
if(dp[idx][i]){
// 含i,所以+1
ret.push_back(s.substr(idx, i-idx+1));
// 加入该串的情况
backtrace(s, i+1);
// 撤回
ret.pop_back();
}
}
}
vector<vector<string>> partition(string s) {
int len = s.size();
// 初始化(和0相关都是true)
dp.resize(len, vector<int>(len, true));
//
for(int i = len-1; i >= 0; i--){
for(int j = i+1; j < len; j++){
dp[i][j] = (s[i] == s[j]) && dp[i+1][j-1];
}
}
backtrace(s, 0);
return res;
}
};