给定一个字符串 s ,请将 s 分割成一些子串,使每个子串都是 回文串 ,返回 s 所有可能的分割方案。
回文串 是正着读和反着读都一样的字符串。
示例 1:
输入:s = “google”
输出:[[“g”,“o”,“o”,“g”,“l”,“e”],[“g”,“oo”,“g”,“l”,“e”],[“goog”,“l”,“e”]]
字符串的回溯,经典
class Solution {
vector<vector<string>> res;
string str;
int slen;
public:
bool isHuiWen(int leftPoint, int rightPoint, int leftEdge, int rightEdge){
int tmpL = leftPoint;
int tmpR = rightPoint;
while(tmpL >= leftEdge && tmpR <= rightEdge) {
if(str[tmpL/2] != str[tmpR/2]) {
return false;
}
tmpL-=2;
tmpR+=2;
}
return true;
}
// 这里的start的范围是从 0 ~ 2 * s.length() - 1
// 但是传递的时候, start 永远是偶数,即停留在实体字符上
// 0、2、4、...、slen-1
void partitionHelper(vector<string> &v, int start) {
if (start >= slen) {
res.push_back(v);
return;
}
int i = start;
// 以j为圆心
//for(int j = i; j < slen; j++)
for(int j = i; 2*j < slen + i; j++) {
//判定以j为中心,左边界到i,右边界小于slen的圆圈是否是回文
//如果是的话,则将园内的数据一股脑儿放到v中,然后从右侧圆外进入纵深
//纵深回来后,再将该数据取出来,继续进行下一个圆心的遍历
//i和j固定后,左半径长度 j-i+1,设右边界为y,则y-j+1 = j-i+1 => y=2*j-i
//所以,j 的范围有如下要求:
// 2*j-i < slen
// 推出 2*j < slen + i
// 因为 i<slen,所以,j<slen 可以缩小为 2*j < slen + i
//圆心j确定后,半径也随之确定,j-i+1 (包括圆心)
//同前一个回文问题,j的下标为奇数时,肯定为*,所以左右侧遍历要从 j-1 和 j+1 向两边扩散
//同前一个回文问题,j的下标为偶数时,肯定为实体字符,所以左右侧遍历要从 j 和 j 向两边扩散
//扩散的步进为2
//该圆满足条件,圆长 (j-1 - i + 1)*2+1 = 2j-2i+1
if(j%2) {
if(isHuiWen(j-1, j+1, i, 2*j-i)) {
v.push_back(str.substr(i/2, (2*j-2*i + 1)/2+1));
partitionHelper(v, 2*j-i+2);
v.pop_back();
}
} else {
if(isHuiWen(j, j, i, 2*j-i)) {
v.push_back(str.substr(i/2, (2*j-2*i + 1)/2+1));
partitionHelper(v, 2*j-i+2);
v.pop_back();
}
}
}
}
vector<vector<string>> partition(string s) {
vector<string> tmp;
slen = 2 * s.length() - 1;
if(slen <= 0) {
return res;
}
str = s;
partitionHelper(tmp, 0);
return res;
}
};
以 abac为例,可以假想为:a * b * a * c
0 1 2 3 4 5 6
a * b * a * c
核心是如下函数:
void partitionHelper(vector<string> &v, int start) {
if (start >= slen) {
res.push_back(v);
return;
}
int i = start;
// 以j为圆心
for(int j = i; 2*j < slen + i; j++) {
if(j%2) {
if(isHuiWen(j-1, j+1, i, 2*j-i)) {
v.push_back(str.substr(i/2, (2*j-2*i + 1)/2+1));
partitionHelper(v, 2*j-i+2);
v.pop_back();
}
} else {
if(isHuiWen(j, j, i, 2*j-i)) {
v.push_back(str.substr(i/2, (2*j-2*i + 1)/2+1));
partitionHelper(v, 2*j-i+2);
v.pop_back();
}
}
}
}