[LeetCode] Palindrome Partitioning

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"]
  ]

解题:

方法一:DFS 

 1 class Solution {
 2     private:
 3             vector<vector<string> >   m_res;
 4     public:
 5         vector<vector<string> > partition(string s)
 6         {
 7             size_t size = s.size();
 8             if(size == 0)
 9                 return m_res;
10 
11             vector<string> str;
12             dfs(s, 0, size - 1, str);
13             return m_res;
14         }
15 
16         void dfs(string s, size_t begin, size_t end, vector<string>& str)
17         {
18             if(begin > end)
19             {
20                 m_res.push_back(str);
21                 return;
22             }
23 
24             for(size_t i = begin; i<=  end; i++)
25             {
26                 if(isPalindrome(s, begin, i))
27                 {
28                     str.push_back(s.substr(begin, i-begin + 1));
29                     dfs(s, i+1, end, str);
30                     str.pop_back();
31                 }
32             }
33         }
34 
35         bool isPalindrome(string s, size_t begin, size_t end)
36         {
37             if(begin == end)
38                 return true;
39             while(begin <= end)
40             {
41                 if(s[begin] == s[end])
42                 {
43                     begin++;
44                     end --;
45                 }
46                 else
47                     return false;
48             }
49             return true;
50         }
51 };

方法二:

http://blog.csdn.net/yutianzuijin/article/details/16850031

DP 具体还没有想清楚,

但是求解任意s[i,j]是否是回文串可以用递归。。

P[i][j] 表示s[i,j] 是否是回文串。隐含条件是i<=j

若i==j,则P[i][j] = true

若i==j-1且s[i]==s[j],则P[i][j] = true

若i==j-1且P[i+1][j-1]],则P[i][j] = true

求解时,一次求解 0~i-1和i是否为回文串,是按照列求解的,

p[i][j]矩阵式一个上三角镇,

11111

01111

00111

00011

00001

获得公式之后,DP算法面临的下一个问题是计算顺序和初始化的问题。P[i][j]依赖于P[i+1][j-1],表示我们必须要从最后一行开始从左到右计算一个上对角矩阵。元素的初始化就是对最左侧的两条斜对角线进行初始化,如下图所示:

上图黄色部分是没有意义的部分,因为i到j的子串中i必须小于等于j。绿色部分表示单个字符的子串,肯定都是回文串。蓝色部分也是需要初始化的部分,因为它依赖于黄色没有意义的部分,该部分的初始化只需要判断两个字符是否相等。

有两步DP:

  1. whether s[i,j] is palindrome
  2. sub palindromes of s[i, n-1]

sub_palins[i] 表示 s[i,n-1]的回文分割的集合,

那么sub_palins[i] = { if(p[i,j])  s[i,j] + 每一个sub_pailns[j]中的 分割 小集合} 对于所有的 i <j <n

对于字符串aabcc,打印出 sub_pailns[i] 中的各个元素:

sub_palins[4]:
c
sub_palins[3]:
c       c
cc
sub_palins[2]:
b       c       c
b       cc
sub_palins[1]:
a       b       c       c
a       b       cc
sub_palins[0]:
a       a       b       c       c
a       a       b       cc
aa      b       c       c
aa      b       cc
class Solution {
    public:
        vector<vector<string> > partition(string s) {
            const int n = s.size();
            bool p[n][n]; // whether s[i,j] is palindrome
            fill_n(&p[0][0], n * n, false);
            for (int i = n - 1; i >= 0; --i)
                for (int j = i; j < n; ++j)
                    p[i][j] = s[i] == s[j] && ((j - i < 2) || p[i + 1][j - 1]);//第一步DP的核心递推式


            vector<vector<string> > sub_palins[n];// 2. 要存下所有的结果,sub_palins[i]:sub palindromes of s[i, n-1]
            for (int i = n - 1; i >= 0; --i) {
                for (int j = i; j < n; ++j)
                    if (p[i][j]) {
                        const string palindrome = s.substr(i, j - i + 1); 
                        if (j + 1 < n) {
                            for (int k = 0; k < sub_palins[j + 1].size(); k++) {//在sub_palins[j + 1]中元素加上palindrome,生成sub_palins[i]中的元素
                                vector<string> v = sub_palins[j+1][k];
                                v.insert(v.begin(), palindrome);//第二步DP的核心递推式
                                sub_palins[i].push_back(v);
                            }   
                        } else { //j = n-1, it meas s[i,j] reach the end of s
                            vector<string> v;
                            v.push_back(palindrome);
                            sub_palins[i].push_back(v);
                        }   
                    }   
            }   
            return sub_palins[0];
        }   
};

加完测试code之后的code

class Solution {
    public:
        vector<vector<string> > partition(string s) {
            const int n = s.size();
            bool p[n][n]; // whether s[i,j] is palindrome
            fill_n(&p[0][0], n * n, false);
            for (int i = n - 1; i >= 0; --i)
                for (int j = i; j < n; ++j)
                    p[i][j] = s[i] == s[j] && ((j - i < 2) || p[i + 1][j - 1]);


            vector<vector<string> > sub_palins[n]; // sub palindromes of s[0,i]
            for (int i = n - 1; i >= 0; --i) {
                for (int j = i; j < n; ++j)
                    if (p[i][j]) {
                        const string palindrome = s.substr(i, j - i + 1);
                        if (j + 1 < n) {
                            for (int k = 0; k < sub_palins[j + 1].size(); k++) {
                                vector<string> v = sub_palins[j+1][k];
                                v.insert(v.begin(), palindrome);
                                sub_palins[i].push_back(v);
                            }
                        } else {
                            vector<string> v;
                            v.push_back(palindrome);
                            sub_palins[i].push_back(v);
                        }
                    }
            }

            for( int i = n -1; i >=0; i--)
            {
                cout << "sub_palins[" << i << "]:" << endl;
                vector<vector<string> > strMatrix = sub_palins[i];
                for(int j = 0; j < strMatrix.size(); j++)
                {
                    vector<string> strVec = strMatrix[j];
                    for(int k = 0; k < strVec.size(); k++)
                        cout << strVec[k] <<"	";
                    cout << endl;
                }
            }
            return sub_palins[0];
        }
};
原文地址:https://www.cnblogs.com/diegodu/p/3853066.html