分割回文串:给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。
返回 s 所有可能的分割方案。
分析:首先要用动态规划来标记出回文子串的位置,dp[i][j]=true表示字串i到j是回文。因此动态规划判断时候是用的
dp[i][j] = (s[i] == s[j]) && (len<3 || dp[i+1][j-1]) 表示当len<3时候只需要判断两个端点,其他时候还要判断中间是否是回文子串。
然后使用回溯法来进行划分,start从0开始,然后判断start到j是否是回文,如果是的话就递归划分剩下的串,回溯后就把刚刚添加进去的子串给pop出来,继续判断下一个j即可
class Solution {
public:
//bool dp[200][200];
vector<vector<string>> partition(string s) {
//先用动态规划的方法来确定每个位置上是否是回文子串
int n = s.size();
vector<vector<string>> ret;
vector<string> currVec;
vector<vector<bool>> dp(n,vector<bool>(n,false));
//vector<vector<bool>> dp;
//得到每个段是否是回文子串
for(int len=1;len<=n;len++){
for(int i=0;i<n;i++){
int j = i + len - 1;
if(j<n){
dp[i][j] = (s[i] == s[j]) && (len < 3 || dp[i+1][j-1]);
}
}
}
//然后通过回溯法来求解子串,先判断本位置左侧的子串是否是回文子串,如果是,就切割右侧子串
//partitionCore(ret,currVec,s,dp,0,n);
partitionCore(ret,currVec,s,
dp,0,n);
/*for(int j=0;j<n;j++){
for(int i=0;i<n;i++){
cout<<static_cast<int>(dp[j][i])<<' ';
}
cout<<endl;
}*/
return ret;
}
//用回溯法来求子串,求得到就继续,求不到就返回
void partitionCore(vector<vector<string>>& ret,vector<string>& currVec,string s,
vector<vector<bool>>& dp,int start,int n){
//递归的出口
if(start >= n){
//说明已经遍历结束了
ret.push_back(currVec);
return;
}
//递归主体
//从开始位置start开始,然后判断不同位置上的子串是否是回文,然后递归来获取剩下部分的回文
for(int j=start;j<n;j++){
//不同的结束位置
if(dp[start][j]){
//判断是否是回文,如果是就要继续找出剩下部分的回文了
currVec.push_back(s.substr(start,j-start+1));
partitionCore(ret,currVec,s,dp,j+1,n);
currVec.pop_back();
}
}
}
};