在于用一个数组判断[i,j]区间是否是回文串,前期需要先预处理回文字符串,枚举最后一个数j,从0开始枚举,每次循环里判断[i~j,j]是否回文,用一个二维数组f[i][j]来判断即可。该步骤时间复杂度为O(n2)
下一步用暴搜,时间复杂度为指数级别
code
class Solution {
public:
vector<vector<string>>ans;
vector<string> path;
vector<vector<bool>>f;
vector<vector<string>> partition(string s) {
int n = s.size();
f = vector<vector<bool>>(n, vector<bool> (n));
for (int j = 0; j < n; j++) { // 右边界从0开始,保证每个都被遍历
for (int i = 0; i <= j; i++) {
if (i == j) f[i][j] = true;
else if (s[i] == s[j]) {
if (i + 1 > j - 1 || f[i + 1][j - 1]) f[i][j] = true;
}
}
}
dfs(s, 0);
return ans;
}
void dfs(string s, int k) {
if (k == s.size()) {
ans.push_back(path);
return;
}
for (int i = k; i < s.size(); i++) {
if (f[k][i]) {
path.push_back(s.substr(k, i - k + 1));
dfs(s, i + 1);
path.pop_back();
}
}
}
};
加强题
预处理一样,最后用一个g[n]来表示序号为n时可以被分为几个回文字符,因为是切割次数,所以在回文字符基础上减一,类似于”abc“,最小为3个回文字符,只需切2刀即可。
class Solution {
public:
int minCut(string s) {
int n = s.size();
s = ' ' + s; // 以便序号对上
vector<vector<bool>>f(n + 1, vector<bool>(n + 1));
vector<int> g(n + 1, 1e8);
for (int j = 1; j <= n; j++) {
for (int i = 1; i <= j; i ++) {
if (i == j) f[i][j] = true;
else if (s[i] == s[j]) {
if (i + 1 > j - 1 || f[i + 1][j - 1]) f[i][j] = true;
}
}
}
g[0] = 0;
for (int j = 1; j <= n; j++) {
for (int i = 1; i <= j; i++) {
if (f[i][j]) g[j] = min(g[j], g[i - 1] + 1); // 判断这个数是否最小,加以即可
}
}
return g[n] - 1;
}
};