分割回文串(attention)

题目

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

思路

分割s,从字串的长度为1开始分割,直至字串的长度为字符串的长度结束,在字符串上根据不同的字串长度按序依次进行分割

class Solution {
public:
    vector<vector<string>> res;
    vector<string> vec;
    string path;
    bool IsPalindromeString(string s)
    {
        int left = 0;
        int right = s.length() - 1;
        while (left < right) {
            if (s[left] != s[right]) {
                return false;
            }
            ++left;
            --right;
        }
        return true;
    }

    bool partitionAux(string s, int substr_length)
    {
        int i;
        for(i = 0; i < s.length(); i += substr_length)
        {
            path = s.substr(i, substr_length);
            if(IsPalindromeString(path))  vec.emplace_back(path);
            else return false;
        }
        return true;
    }
    vector<vector<string>> partition(string s) {
        for(int i = 1; i <= s.length(); ++i)
        {
            vec.clear(); path.clear();
            if(partitionAux(s, i)) res.emplace_back(vec);
        }
        return res;
    }
};

错了,做了一个小时多一点,忽略了最关键的一点,在字串长度的条件下,可以有多种组合情况,而不是按照顺序一个字串一个字串的组合

自己又看了半个小时

看代码随想录

image-20240420103735738

class Solution {
public:
    vector<vector<string>> res;
    vector<string> vec;
    string path;
    bool IsPalindromeString(string s)
    {
        int left = 0;
        int right = s.length() - 1;
        while (left < right) {
            if (s[left] != s[right]) {
                return false;
            }
            ++left;
            --right;
        }
        return true;
    }

    void partitionAux(string s, int start_index)
    {
        for(int i = 1; i <= s.length() - start_index; ++i)
        {
            path = s.substr(start_index, i);
            if(IsPalindromeString(path))  vec.emplace_back(path);
            else return;
            if(start_index + i == s.length()) 
            {
                res.emplace_back(vec);
                vec.pop_back();
            }
            else partitionAux(s, start_index + i);
            vec.pop_back();
        }
    }
    vector<vector<string>> partition(string s) {
        partitionAux(s, 0);
        return res;
    }
};

完全不知道题意,对切割问题没有概念

优化

对回文的判断进行优化,上述代码isPalindrome函数运用双指针的方法来判定对于一个字符串s, 给定起始下标和终止下标, 截取出的子字符串是否是回文字串。但是其中有一定的重复计算存在:

例如给定字符串"abcde", 在已知"bcd"不是回文字串时, 不再需要去双指针操作"abcde"而可以直接判定它一定不是回文字串。

具体来说, 给定一个字符串s, 长度为n, 它成为回文字串的充分必要条件是s[0] == s[n-1]s[1:n-1]是回文字串。

大家如果熟悉动态规划这种算法的话, 我们可以高效地事先一次性计算出, 针对一个字符串s, 它的任何子串是否是回文字串, 然后在我们的回溯函数中直接查询即可, 省去了双指针移动判定这一步骤.

class Solution {
private:
    vector<vector<string>> result;
    vector<string> path; // 放已经回文的子串
    vector<vector<bool>> isPalindrome; // 放事先计算好的是否回文子串的结果
    void backtracking (const string& s, int startIndex) {
        // 如果起始位置已经大于s的大小,说明已经找到了一组分割方案了
        if (startIndex >= s.size()) {
            result.push_back(path);
            return;
        }
        for (int i = startIndex; i < s.size(); i++) {
            if (isPalindrome[startIndex][i]) {   // 是回文子串
                // 获取[startIndex,i]在s中的子串
                string str = s.substr(startIndex, i - startIndex + 1);
                path.push_back(str);
            } else {                                // 不是回文,跳过
                continue;
            }
            backtracking(s, i + 1); // 寻找i+1为起始位置的子串
            path.pop_back(); // 回溯过程,弹出本次已经添加的子串
        }
    }
    void computePalindrome(const string& s) {
        // isPalindrome[i][j] 代表 s[i:j](双边包括)是否是回文字串 
        isPalindrome.resize(s.size(), vector<bool>(s.size(), false)); // 根据字符串s, 刷新布尔矩阵的大小
        for (int i = s.size() - 1; i >= 0; i--) { 
            // 需要倒序计算, 保证在i行时, i+1行已经计算好了
            for (int j = i; j < s.size(); j++) {
                if (j == i) {isPalindrome[i][j] = true;}
                else if (j - i == 1) {isPalindrome[i][j] = (s[i] == s[j]);}
                else {isPalindrome[i][j] = (s[i] == s[j] && isPalindrome[i+1][j-1]);}
            }
        }
    }
public:
    vector<vector<string>> partition(string s) {
        result.clear();
        path.clear();
        computePalindrome(s);
        backtracking(s, 0);
        return result;
    }
};

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top