Leetcode 131&132. Palindrome Partitioning I & II

131. Palindrome Partitioning

topic

Given a string s, partition s such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of s.
For example, given s = “aab”,
Return

[
  ["aa","b"],
  ["a","a","b"]
]

Topic Analysis

This question asks to find all possible permutations of palindromic substrings. The idea I took was to find all the substrings of the string that are palindrome strings, then generate a graph like that, and use a depth-first search to get the results. I save the result of the substring in a map<int,set<int> >, map[i]representing the iposition as the starting point, and the length that can form a palindrome string is j.

code

code show as below:

class Solution {
public:
// 判断是否是回文子串
    bool valid(string s)
    {
        string s1 = s;
        reverse(s1.begin(), s1.end());
        if (s1 == s)
            return true;
        return false;
    }

// 深度优先搜索构建
    void solve(map<int, vector<int>> &mii, int idx, vector<vector<string>> &vvs, string s,vector<string> &vs)
    {
        if (idx == s.size())
        {
            vvs.push_back(vs);
            return;
        }
        else
        {
            vector<int> v = mii[idx];
            for (int i = 0; i < v.size(); ++i)
            {
                vs.push_back(s.substr(idx, v[i]));
                solve(mii, idx + v[i], vvs, s, vs);
                vs.pop_back();
            }
        }
    }

// 生成回文子串
    vector<vector<string>> partition(string s) {
        vector<vector<string>> vvs;
        map<int, vector<int> > mii;
        vector<string> vs;        
        int length = 1;
        for (; length <= s.size(); ++length)
        {
            for (int i = 0; i < s.size(); ++i)
            {
                if (i + length <= s.size())
                {
                    if (valid(s.substr(i, length)))
                    {
                        mii[i].push_back(length);
                    }
                }
                else
                {
                    break;
                }
            }
        }   
        solve(mii, 0, vvs, s, vs);
        /*for (int i = 0; i < vvs.size(); ++i)
        {
        for (int j = 0; j < vvs[i].size(); ++j)
        cout << vvs[i][j] << " ";
        cout << endl;
        }*/
        return vvs;
    }
};

132. Palindrome Partitioning II

topic

Given a string s, partition s such that every substring of the partition is a palindrome.
Return the minimum cuts needed for a palindrome partitioning of s.
For example, given s = "aab",
Return 1 since the palindrome partitioning ["aa","b"]could be produced using1cut.

Topic Analysis

This question asks to give a shortest segmentation result.
Of course, the most direct idea is to use the results obtained in the previous question to obtain the minimum value among all possible divisions, but this intuitive feeling will definitely time out, otherwise I am sorry that this question is harddifficult haha.

idea one

Think of the idea of ​​using similar dynamic programming: f[n] = min(f[i]+1), which s[i,n]constitutes a palindrome string. Two layers of loops are added to determine whether it is a palindrome string, but the last test case times out, a 1400character long ==.
code show as below:

bool valid(string s)
{
    string s1 = s;
    reverse(s1.begin(), s1.end());
    if (s1 == s)
        return true;
    return false;
}

int minCut(string s) {
    if(s.size()<=1)
        return 0;
    vector<int> fn(s.size()+1, -1);
    for (int i = 1; i <= s.size(); ++i)
    {
        int minDis = INT_MAX;
        for (int j = 0; j < i; ++j)
        {           
            if (valid(s.substr(j,i-j)))
            {
                minDis = min(fn[j] + 1, minDis);
            }
        }
        fn[i] = minDis;
    }
    return fn[s.size()];
}

idea two

Thinking about why it times out for a while, it should be repeated calculation for the same string, so using the memo string, the record is a palindrome string and a substring that is not a palindrome string, but it still times out. After a closer look, this memorandum method does not work, because in my writing method, each will only be calculated once, and the memorandum method has no effect. The memo is still useful == the
code is as follows:

class Solution {
public:
        map<int, set<int>> mii; // 回文串
        map<int, set<int>> miix;// 不是回文串
    bool valid(string s, int i, int j)
    {
        if (mii[i].count(j))
            return true;
        if (miix[i].count(j))
            return false;
        string s1 = s.substr(i, j);
        string s2 = s1;
        reverse(s1.begin(), s1.end());
        if (s1 == s2)
        {
            mii[i].insert(j);
            return true;
        }
        else
        {
            miix[i].insert(j);
            return false;
        }

    }
    int minCut(string s) {
        if (s.size() <= 1)
            return 0;
        vector<int> fn(s.size() + 1, -1);
        for (int i = 1; i <= s.size(); ++i)
        {
            int minDis = INT_MAX;
            for (int j = 0; j < i; ++j)
            {
                if (valid(s, j, i - j))
                {
                    minDis = min(fn[j] + 1, minDis);                
                }
            }
            fn[i] = minDis;
        }
        return fn[s.size()];
    }
};

idea three

After thinking about it, the dynamic programming idea of ​​the previous method is correct, but the time should be wasted on judging the palindrome string. Due to laziness, this way of writing is very time-consuming for the string brothers with more than 1,000 lengths in the test case. After thinking about how to slow down the time, I saw the solution of the Great God on the Internet, and I suddenly realized, the link , and finally AC, so open.
Here comes the point : For judging whether a string is a palindrome, [i,j]the following conditions must be met to determine whether a string is a string, s[i]==s[j] && vvi[i+1][j-1]=trueand of course there are cases where the [i,j]length is less than or equal to 1.
code show as below:

class Solution {
public:
    int minCut(string s) {
        if (s.size() <= 1)
            return 0;
        vector<int> fn(s.size()+1, 0);
        vector<vector<bool>> vvi(s.size(), vector<bool>(s.size(), false));
        for (int i = s.size()-1; i >=0; --i)
        {
            int minDis = INT_MAX;
            for (int j = i; j<s.size(); ++j)
            {
                if ((s[i] == s[j]) && ((j - i <= 1) || vvi[i + 1][j - 1]))
                {
                    vvi[i][j] = true;
                    minDis = min(fn[j+1] + 1, minDis);  
                }            
            }       
            fn[i] = minDis;
        }
        return fn[0]-1;
    }
};

Corrections are welcome.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325769467&siteId=291194637