[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:
- whether s[i,j] is palindrome
- 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] <<"\t"; cout << endl; } } return sub_palins[0]; } };