力扣 132. 分割回文串 II dp bfs/dfs 剪枝

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[ij]是回文串,则 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 n1的最短路径,直接 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[0i]所需要的最少次数,那么有转移方程: 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[j1]+1),当然我们需要确保 s [ j … i ] s[j…i] s[ji]也是一个回文串。

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];
    }
};

猜你喜欢

转载自blog.csdn.net/xiji333/article/details/114540265