此道题目,我一开始在代码中用的dp数组是栈数组,发现速度比较慢。看了别人的解法,发现用动态数组更快。注意动态二维数组的用法,以及如何释放内存。
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"] ]
分析:首先对字符串的所有子串判断是否是回文,设f[i][j] = true表示以i为起点,长度为j的子串是回文,等于false表示不是回文,那么求f[i][j]的动态规划方程如下:
-
当j = 1,f[i][j] = true;
-
当j = 2,f[i][j] = (s[i]==s[i+1]),其中s是输入字符串
-
当j > 2, f[i][j] = f[i+1][j-2] && (s[i] == s[i+j-1])(即判断s[m..n]是否是回文时:只要s[m+1...n-1]是回文并且s[m] = s[n],那么它就是回文,否则不是回文)
这一题也可以不用动态规划来求f,可以用普通的判断回文的方式判断每个子串是否为回文。
求得f后,根据 f 可以构建一棵树,可以通过DFS来枚举所有的分割方式,代码如下:
class Solution {
public:
vector<vector<string>> partition(string s) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
vector< vector<string> >res;
int len = s.length();
if(len == 0)return res;
//f[i][j] = true表示以i为起点,长度为j的子串是回文
bool **f = new bool*[len];
for(int i = 0 ; i < len; i++)
{
f[i] = new bool[len+1];
for(int j = 0; j < len+1; j++)
f[i][j] = 0;
f[i][1] = true;
}
for(int k = 2; k <= len; k++)
{
for(int i = 0; i <= len-k; i++)
{
if(k == 2)f[i][2] = (s[i] == s[i+1]);
else f[i][k] = f[i+1][k-2] && (s[i] == s[i+k-1]);
}
}
vector<string> tmp;
DFSRecur(s, f, 0, res, tmp);
for(int i = 0 ; i < len; i++)
delete [](f[i]);
delete []f;
return res;
}
void DFSRecur(const string &s, bool **f, int i,
vector< vector<string> > &res, vector<string> &tmp)
{//i为遍历的起点
int len = s.length();
if(i >= len){res.push_back(tmp); return;}
for(int k = 1; k <= len - i; k++)
if(f[i][k] == true)
{
tmp.push_back(s.substr(i, k));
DFSRecur(s, f, i+k, res, tmp);
tmp.pop_back();
}
}
};