给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。
返回 s 所有可能的分割方案。
示例:
输入: "aab"
输出:
[
["aa","b"],
["a","a","b"]
]
回溯法
bool isPalindrome(string s,int start,int i){
while(start<=i){
if(s[start]!=s[i]) return false;
start++;
i--;
}
return true;
}
void dfs(string s,int start,vector<string> out,vector<vector<string>>&res){
if(start==s.size()) res.push_back(out);
else{
for(int i=start;i<s.size();++i){
if(!isPalindrome(s,start,i)) continue;
out.push_back(s.substr(start,i-start+1));
dfs(s,i+1,out,res);
out.pop_back();
}
}
}
vector<vector<string>> partition(string s) {
vector<vector<string>> res;
vector<string> out;
dfs(s,0,out,res);
return res;
}
改进
之前的方法每一个子串都要独自判断,可以先建立好字符串s的子串回文的dp数组。当我们建立好这样一个二维数组dp,其中 dp[i][j] 表示 [i, j] 范围内的子串是否为回文串,这样就不需要另外的子函数去判断子串是否为回文串了,大大的提高了计算的效率。
void dfs(string s,int start,vector<string> out,vector<vector<string>>&res,vector<vector<int>> dp){
if(start==s.size()) res.push_back(out);
else{
for(int i=start;i<s.size();++i){
if(!dp[start][i]) continue;
out.push_back(s.substr(start,i-start+1));
dfs(s,i+1,out,res,dp);
out.pop_back();
}
}
}
vector<vector<string>> partition(string s) {
int n=s.size();
vector<vector<string>> res;
vector<string> out;
vector<vector<int>> dp(n,vector<int>(n,0));
//需要j在外层循环
for(int j=0;j<n;++j)
for(int i=0;i<=j;++i){
if(j-i<2) dp[i][j]=(s[i]==s[j]);
else if(s[i]==s[j]&&dp[i+1][j-1]) dp[i][j]=1;
}
dfs(s,0,out,res,dp);
return res;
}