回溯一直学不会,慢慢来吧。记录一下一些思考过程。争取下次能照葫芦画瓢.
class Solution {
/**
* @param String $s
* @return String[][]
*/
protected $res = [];
protected $dp = [];
function partition($s) {
$len_s = strlen($s);
$this->dp = array_fill(0, $len_s, array_fill(0, $len_s, false));
for ($i = 0; $i < $len_s; $i++) {
$this->preProcess($s, $i, $i);
$this->preProcess($s, $i, $i + 1);
}
$this->help131($s, 0, $len_s, []);
return $this->res;
}
protected function help131($s, $start, $len_s, $path) {
if ($len_s === $start) {
$this->res[] = $path;
return;
}
//aabcdd
//我们可以依次选择一个前缀字符串,然后一个结果就是
//比如我们选择字符串 a, 那么一个结果是 a + "abcdd"的结果
//同样可以继续选择字符串 aa,那么一个结果是 aa + "bcdd"的结果
for ($i = $start; $i < $len_s; $i++) {
$pre = substr($s, $start, $i - $start + 1);
//上面的pre 和下面函数里判断的字符串就是我们所谓的前缀,要是前缀都不是回文的话直接跳过这个选择。
// if (false === $this->isHuiwen($s, $start, $i)) {
// continue;
// }
if ($this->dp[$start][$i] === false) {
continue;
}
//前缀是回文的话,那么我们继续去下一层找剩余串的结果
$path[] = $pre;
//当前位置用过的字符不能继续使用了,这个相当于在剩余的字符串里选择找结果。
$this->help131($s, $i+1, $len_s, $path);
//以 a 做前缀的路径处理完了,回溯一下,下次循环准备找以 aa 为前缀的字符串了。
array_pop($path);
}
}
//中心法扩展
protected function preProcess($s, $left, $right) {
$len_s = strlen($s);
while ($left >= 0 && $right < $len_s && $s[$left] == $s[$right]) {
$this->dp[$left][$right] = true;
$left--;
$right++;
}
}
protected function isHuiwen($s, $i, $j) {
while ($i < $j) {
if ($s[$i] === $s[$j]) {
$i++;
$j--;
} else {
return false;
}
}
return true;
}
}
这张图比较形象的解释了整个切割的过程。