131.分割回文串

【LetMeFly】131.分割回文串:暴力解法

力扣题目链接:https://leetcode.cn/problems/palindrome-partitioning/

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。

回文串 是正着读和反着读都一样的字符串。

 

示例 1:

输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]

示例 2:

输入:s = "a"
输出:[["a"]]

 

提示:

  • 1 <= s.length <= 16
  • s 仅由小写英文字母组成

方法一:状态压缩,暴力解法

字符串的长度最大为16,$2^{16}\times 16^2=16,777,216$,实际并不会弯完全执行,可在$1s$内解决。

因此不如枚举“分割位置”,然后判断分割后的子串是否都是回文串。

因为长度为$n$的字符串最多切$n-1$刀,那么我们可以用$i$从$0$到$2^{n-1}$枚举切割状态。

如果二进制下$i$的第$j$位为$1$,那么就在原字符串第$i+1$个字符后面切一刀。

  • 时间复杂度$O(2^n\times n^2)$,其中$n$是字符串的长度
  • 空间复杂度$O(n)$,只需要把某次的切割结果存起来(答案不计入算法空间复杂度)

AC代码

C++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Solution {
private:
inline bool ok(string& s) {
for (int i = 0; i < s.size() / 2; i++) {
if (s[i] != s[s.size() - i - 1])
return false;
}
return true;
}
public:
vector<vector<string>> partition(string s) {
int n = s.size() - 1; // 不如n直接-1
vector<vector<string>> ans;
for (int i = 0; i < (1 << n); i++) { // 枚举切割状态
int lastLoc = 0;
vector<string> thisSplited;
string thisStr;
for (int j = 0; j < n; j++) { // 看第j位是否为1
if (i & (1 << j)) {
thisStr = s.substr(lastLoc, j + 1 - lastLoc);
if (!ok(thisStr)) {
goto loop;
}
thisSplited.push_back(thisStr);
lastLoc = j + 1;
}
}
thisStr = s.substr(lastLoc, s.size() - lastLoc); // 切k刀会生成k+1个子串,记得把最后一个子串统计进来
if (!ok(thisStr))
goto loop;
thisSplited.push_back(thisStr);
ans.push_back(thisSplited);
loop:;
}
return ans;
}
};

同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/125946017


131.分割回文串
https://blog.letmefly.xyz/2022/07/23/LeetCode 0131.分割回文串/
作者
Tisfy
发布于
2022年7月23日
许可协议