https://leetcode-cn.com/problems/palindrome-partitioning-ii/
思路一:先 O ( n 2 ) O(n^2) O(n2)预处理出 d p dp dp数组,若 s [ i … j ] s[i…j] s[i…j]是回文串,则 d p i j = 1 dp_{ij}=1 dpij=1。我们可以把这个数组当作一个邻接矩阵,即把 d p i j = 1 dp_{ij}=1 dpij=1抽象为 i i i到 j j j的一条边,最终可以得到一个图,那么答案就等于从 0 0 0开始到 n − 1 n-1 n−1的最短路径,直接 b f s bfs bfs即可。
class Solution {
public:
int bfs(const vector<vector<bool>> &dp,int n)
{
queue<int> q;
vector<int> step(n+1);
q.push(0);
while(!q.empty())
{
int fon=q.front();
if(fon==n)
break;
q.pop();
for(int i=fon;i<n;i++)
if(dp[fon][i]&&!step[i+1])
q.push(i+1),step[i+1]=step[fon]+1;
}
return step[n]-1;
}
int minCut(string s) {
int n=s.size();
vector<vector<bool>> dp(n,vector<bool>(n));
dp[0][0]=1;
for(int i=1;i<n;i++)
{
dp[i][i]=1;
if(s[i]==s[i-1])
dp[i-1][i]=1;
}
for(int len=3;len<=n;len++)
{
for(int i=0;i+len-1<n;i++)
{
int j=i+len-1;
if(s[i]==s[j]&&dp[i+1][j-1])
dp[i][j]=1;
}
}
return bfs(dp,n);
}
};
思路二:依然要先预处理,然后设 f [ i ] f[i] f[i]表示分割 s [ 0 … i ] s[0…i] s[0…i]所需要的最少次数,那么有转移方程: f [ i ] = m i n ( f [ i ] , f [ j − 1 ] + 1 ) f[i]=min(f[i],f[j-1]+1) f[i]=min(f[i],f[j−1]+1),当然我们需要确保 s [ j … i ] s[j…i] s[j…i]也是一个回文串。
class Solution {
public:
int minCut(string s) {
int n=s.size();
vector<vector<bool>> dp(n,vector<bool>(n));
dp[0][0]=1;
for(int i=1;i<n;i++)
{
dp[i][i]=1;
if(s[i]==s[i-1])
dp[i-1][i]=1;
}
for(int len=3;len<=n;len++)
{
for(int i=0;i+len-1<n;i++)
{
int j=i+len-1;
if(s[i]==s[j]&&dp[i+1][j-1])
dp[i][j]=1;
}
}
vector<int> f(n,0x3f3f3f3f);
for(int i=0;i<n;i++)
{
if(dp[0][i])
f[i]=0;
else
{
for(int j=1;j<=i;j++)
if(dp[j][i])
f[i]=min(f[i],f[j-1]+1);
}
}
return f[n-1];
}
};
思路三: d f s dfs dfs,和 b f s bfs bfs的思想差不多,但是它不能保证当前解是最优解,所以直接爆搜的话会超时,需要加上记忆化剪枝。
class Solution {
public:
void dfs(int idx,int curtimes,int n,vector<int> &ans,vector<vector<bool>>& dp)
{
if(idx==n)
return;
for(int i=n-1;i>=idx;i--)
{
//剪枝
if(dp[idx][i]&&curtimes<ans[i])
{
//记忆化
ans[i]=curtimes;
dfs(i+1,curtimes+1,n,ans,dp);
}
}
}
int minCut(string s) {
int n=s.size();
vector<vector<bool>> dp(n,vector<bool>(n));
dp[0][0]=1;
for(int i=1;i<n;i++)
{
dp[i][i]=1;
if(s[i]==s[i-1])
dp[i-1][i]=1;
}
for(int len=3;len<=n;len++)
{
for(int i=0;i+len-1<n;i++)
{
int j=i+len-1;
if(s[i]==s[j]&&dp[i+1][j-1])
dp[i][j]=1;
}
}
vector<int> ans(n,0x3f3f3f3f);
dfs(0,0,n,ans,dp);
return ans[n-1];
}
};