Leetcode PalindromePartitioning(C++ Solution)
分割回文串
动态规划 DFS
问题描述
给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。
返回 s 所有可能的分割方案。
样例
输入: "aab"
输出:
[
["aa","b"],
["a","a","b"]
]
输入: "efe"
输出:
[
["efe"],
["e","f","e"]
]
提示
nothing
思路(Algorithm)
DP
先通过动态规划,预处理字符串,得到矩阵isPalindrome,isPalindrome[i][j]=true的含义是s[i,j](s的字串)是Palindrome;
关系式:
i
s
P
a
l
i
n
d
r
o
m
e
[
i
]
[
j
]
=
(
i
=
=
j
)
∨
(
i
=
=
j
−
1
∧
s
[
i
]
=
=
s
[
j
]
)
∨
(
s
[
i
]
=
=
s
[
j
]
∧
i
s
P
a
l
i
n
d
r
o
m
e
[
i
+
1
]
[
j
−
1
]
)
isPalindrome[i][j] = (i==j) \lor (i==j-1 \land s[i]==s[j]) \lor (s[i]==s[j] \land isPalindrome[i+1][j-1])
isPalindrome[i][j]=(i==j)∨(i==j−1∧s[i]==s[j])∨(s[i]==s[j]∧isPalindrome[i+1][j−1])
解释:该字串为回文串 iff 它是单字符或它是两个相同字符或它的首尾相同且去掉首尾的中间字串是回文
DFS(这是我没想到的,可恶)
基本思路:
给定一个字符串s,从第一个字符开始,如果以它为首的子串是回文,就继续以相同方法搜索子串,直至找到最后一个字符。
具体实现:
- 使用基本的DFS框架;
- preprocess:将当前子串记录进onePartition(也即当前方案);
- postprocess:将当前子串从onePartition(也即当前方案)中删除;
- 当给定index是n是,将当前方案记录入ret(最终的方案总和)。
实现代码(Implement)
#include<vector>
using namespace std;
class Solution {
private:
vector<vector<bool>> isPalindrome;
vector<vector<string>> ret;
vector<string> onePartition;
public:
// DFS
void dfs(const string& s, int i) {
int n = s.size();
if (i == n) {
ret.push_back(onePartition);
return;
}
for (int j = i; j < n; j++) {
if (isPalindrome[i][j]) {
onePartition.push_back(s.substr(i, j - i + 1));
dfs(s, j + 1);
onePartition.pop_back();
}
}
}
// DP
vector<vector<string>> partition(string s) {
if (s.size() == 0) return ret;
int n = s.size();
isPalindrome.assign(n,vector<bool>(n,false));
for (int i = n - 1; i >= 0; i--) {
for (int j = i; j < n; j++) {
isPalindrome[i][j] = (i == j || (i == j - 1 && s[i] == s[j]) || (s[i] == s[j] && isPalindrome[i+1][j-1]));
}
}
dfs(s, 0);
return ret;
}
};
复杂度分析
时间复杂度
O( n ∗ 2 n n*2^n n∗2n), 最坏情况下,存在 2 n − 1 2^{n-1} 2n−1中分割方案
空间复杂度
O( n ∗ 2 n n*2^n n∗2n)
声明
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-partitioning
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。