131.分割回文串

🖇 131.分割回文串

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。

回文串 是正着读和反着读都一样的字符串。

思路

基本思想

开始第一想法是将一个字符串的所有分割结果列出来,统计其中所有的回文串,但是这种方法不符合题意,题目要求将字符串进行分割,分割的每一个子串都要求是回文串,而不是简单的从幂集中找出所有的回文串

所以需要使用回溯法进行搜索,当前子串是回文串,才能进行下一步分割,当前子串不是回文串,需要一直向后搜索,直到到了字符串末尾或者找到一个回文子串

一旦找到一个回文子串,剩下的部分就可以继续分割,继续分割可以使用回溯法,从当前位置的下一位置开始分割,也就是回溯法

当形成一个完整的分割方法时,分割位置走到了字符串的末尾,这是一个标志,代表着形成了一个完整的分割结果,因为只有前面的分割结果是回文串,才能对后面剩余的字符串进行分割

形成一个完整的分割结果之后,需要搜索下一个完整的分割结果,所以需要一步一步回溯,此时保存分割结果的path就需要一步一步的删除元素

执行流程

  1. 回溯法分割字符串,当前子串是回文串才对后面的字符串进行分割
  2. 将当前分割结果加入path
  3. 对剩下的字符串进行分割
  4. 形成完整的分割结果返回时,path需要删除元素

代码

根据以上分析,得出以下代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Solution {
public:
    //存储每个分割的回文串结果
    vector<vector<string>> res;
    vector<string> path;
    vector<vector<string>> partition(string s) {
        if(s.size()==0)
            return res;
        backtrack(s,0,s.size());
        return res;
    }
    //判断一个字符串是不是回文串
    bool isPalindrome(string s,int start,int end){
        for(int i=start,j=end;i<j;++i,--j){
            if(s[i]!=s[j])
                return false;
        }
        return true;
    }
    void backtrack(string s,int index,int n){
        if(index==n){
            res.push_back(path);
            return;
        }
        //开始分割字符串
        for(int i=index;i<n;++i){
            //当前子串是回文串,后面剩下的才需要分割,否则当前子串还需要继续增加
            if(isPalindrome(s,index,i)){
                path.push_back(s.substr(index,i-index+1));
                backtrack(s,i+1,n);
                //当前分割方法统计完成需要回溯
                path.pop_back();
            }
            //不是回文串,继续向后尝试分割,当前子串不需要分割
        }
    }
}

总结

主要是形成一个回文串,才可以对剩余的字符串进行分割,所以分割和回溯的逻辑都写在了if语句里面,形成一个完整的分割结果时,将分割结果存储到res中