题目:131. 分割回文串
思路:求出所有分割方案,可以用回溯、也可以使用位运算。
有两种回溯的方法:
1、采用方法dfs1(),参数为每次分割的左端点
2、采用方法dfs2(),参数为每次分割的左端点、右端点
位运算方法solve(),枚举分割点。
以上三种方法的时间复杂度均为0(2^n)。
判断是否为回文串,可以采用动态规划,通过0(n^2)的时间复杂度完成,避免大量的重复运算。
两种动态规划方法:
1、采用方法dp1(),通过枚举区间长度开始。
2、采用方法dp2(),从右往左开始。
细节看注释
class Solution {
public:
//状态f[i][j],表示区间[i,j]是否为回文串。
vector<vector<int>> f;
//数组v是记录所有分割方案
vector<vector<string>> v;
//记录分割情况
vector<string> tmp;
//字符串的长度
int n;
//判断是否为回文串:动态规划方法一
void dp1(string s){
//初始化为0
f.assign(n,vector<int>(n,0));
//枚举区间的长度lens
for(int lens=1;lens<=n;lens++){
//枚举区间左端点
for(int left=0;left+lens-1<n;left++){
//区间右端点
int right=left+lens-1;
//长度为1,自然是回文串
//长度为2,判断字符是否相等s[left]==s[right]
if(lens==1) f[left][right]=1;
else if(lens==2) f[left][right]=(s[left]==s[right]);
else f[left][right]=f[left+1][right-1]&&(s[left]==s[right]);
}
}
}
//判断是否为回文串:动态规划方法二
void dp2(string s){
//初始化为1
f.assign(n,vector<int>(n,1));
//枚举区间左端点
for(int i=n-1;i>=0;i--){
//区间右端点
for(int j=i+1;j<n;j++){
//从后往前的原因:在于区间f[i][j]的状态是由f[i+1][j-1]转移而来的。
//如果从前往后,那f[i+1][j-1]这里还没有判断。
//不像方法一是枚举区间,f[i+1][j-1]自然是判断过的
f[i][j]=f[i+1][j-1]&&(s[i]==s[j]);
}
}
}
//回溯方法1,参数u为每次分割的左端点
void dfs1(string s,int u){
//前面均合法
if(u==n){
//记录该分割方案
v.push_back(tmp);
return ;
}
//开始枚举分割的右端点
for(int i=u;i<n;i++){
//区间[u,i]符合回文串
if(f[u][i]){
//插入到tmp中进行记录
tmp.push_back(s.substr(u,i-u+1));
//接着dfs
dfs1(s,i+1);
//回溯后需要弹出,避免混乱
tmp.pop_back();
}
}
}
//参数u、start为每次分割的左端点、右端点
void dfs2(string s,int u,int start){
//到达边界
if(u==n){
//如果相等,说明前面的都已经合法
if(u==start){
v.push_back(tmp);
}
return;
}
//区间[u,i]符合回文串,可以分割
//这也是为什么u==n时,要判断u==start的原因。因为start<u时,一定经过该操作
if(f[start][u]){
tmp.push_back(s.substr(start,u-start+1));
//dfs
dfs2(s,u+1,u+1);
tmp.pop_back();
}
//不选u作为右端点
dfs2(s,u+1,start);
}
//位运算
void solve(string s){
//枚举分割点
for(int i=1;i<(1<<n);i++){
bool flag=1;
int start=0;
tmp.clear();
for(int j=0;j<n;j++){
if(i>>j&1){
//区间[start,j]是回文串
if(f[start][j]){
tmp.push_back(s.substr(start,j-start+1));
start=j+1;
}else{
//不是的话,直接退出
flag=0;
break;
}
}
}
//最后一个点必须要分割到,不然少一部份
if((i>>(n-1)&1)==0){
flag=0;
}
if(flag){
v.push_back(tmp);
}
}
}
vector<vector<string>> partition(string s) {
n=s.size();
//dp1(s);
dp2(s);
//dfs1(s,0);
//dfs2(s,0,0);
solve(s);
return v;
}
};