leetcode 132 分割回文串II(dp)

题目描述:

 题解:一开始的时候想着用区间dp。dp[i][j]表示s[i~j]分割为会文子串的最少分割次数。状态转移也很简单,要么s[i~j]本身是回文串不需要分割;

要么枚举分隔点K,dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]+1);代码如下:

class Solution {
public:
    int minCut(string s) {
        int Len = s.length();
        int dp[Len][Len];
        for(int i=0;i<Len;i++)
        {
            for(int j=0;j<Len;j++) dp[i][j] = INT_MAX;
        }
        for(int i=0;i<Len;i++) dp[i][i] = 0;

        for(int l = 2;l<=Len;l++)
        {
            for(int i = 0;i+l-1<Len;i++)
            {
                int j = i+l-1;
                
                if(s[i] == s[j])
                {
                    if(l == 2 || dp[i+1][j-1] == 0) 
                    {
                        // cout <<i <<" " << j <<endl;
                        dp[i][j] = 0;
                        continue;
                    }   
                }

                for(int k = i;k<j;k++)
                {
                    dp[i][j] = min(dp[i][j],dp[i][k]+dp[k+1][j]+1);
                }
            }
        } 
        
        return dp[0][Len-1];
    }
};

 但是这么做的话时间复杂度为o(n^3),果不其然超时了。可以改进的地方有两点:

1. 枚举K的时候,不需要遍历所有情况,只需要枚举s[i~k]或者s[k+1~j]有一个为回文串的情况。

2. 不需要用区间dp的板子,二维的dp三维的遍历,时间复杂度太高了。

新定义一个dp:dp[i]表示s[0~i]分割为回文子串需要的最少分割次数。状态转移结合改进点1进行处理就好。

值得提一下的时候这里判断一个子串是不是回文子串,可以预先用一个二维的dp处理掉。预处理的dp我借鉴了一下别人的代码,自己想的状态转移又是O(n^3)的.....

AC代码:

class Solution {
public:
    int minCut(string s) {
        int Len = s.length();
        int judge[Len][Len];
        for(int i = 0;i<Len;i++)
        {
            for(int j=0;j<Len;j++) judge[i][j] = 0;
        }
        
     // 判断s[left][right]是不是回文串,由于judge[left][right]需要根据judge[left+1][right-1]转移
     // 那么在遍历的时候,第一维遍历right,这样就能保证有序的进行状态转移
for(int right = 0;right<Len;right++) { for(int left = 0;left<=right;left++) { if(left == right) judge[left][right] = 1; else { if(right - left == 1) { if(s[left] == s[right]) judge[left][right] = 1; } else { if(s[left] == s[right]) judge[left][right] = judge[left+1][right-1]; } } } } //cout << judge[0][2] <<endl; int dp[Len]; dp[0] = 0; for(int i=1;i<Len;i++) dp[i] = INT_MAX; for(int i=1;i<Len;i++) { if(judge[0][i] == 1) { dp[i] = 0; continue; } for(int j=0;j<i;j++) { if(judge[j+1][i] == 1) { dp[i] = min(dp[i],dp[j]+1); } } } return dp[Len-1]; } };
原文地址:https://www.cnblogs.com/z1141000271/p/12461186.html