Bootstrap

(nice!!!)(LeetCode 每日一题) 1278. 分割回文串 III(动态规划dp、字符串)

题目:1278. 分割回文串 III

在这里插入图片描述

思路:对于某一段字符串,将其修改为回文串的最少次数是可以通过动态规划得出的。
接着再通过动态规划得出:某一段划分为k个字符串,且满足均为回文串的最小次数。时间复杂度为0(n^3).

C++版本:

class Solution {
public:
    int n=0;
    vector<vector<int>> v;
    //动态规划一:得出字符串修改为回文串的最小次数
    void dp1(string s){
        for(int lens=2;lens<=n;lens++){
            for(int i=0;i+lens-1<n;i++){
                int j=i+lens-1;
                v[i][j]=v[i+1][j-1]+(s[i]!=s[j]);
            }
        }
    }
    //动态规划二:得出字符串修改为回文串的最小次数
    void dp2(string s){
        for(int i=n-2;i>=0;i--){
            for(int j=i+1;j<n;j++){
                v[i][j]=v[i+1][j-1]+(s[i]!=s[j]);
            }
        }
    }

    int palindromePartition(string s, int k) {
        n=s.size();
        v.assign(n,vector<int>(n,0));
        dp1(s);
        //dp2(s);
        //动态规划三:某一段划分为k个字符串,且满足均为回文串的最小次数
        //状态f[k][n]:再在区间[0,n]之间划分k次,且均为回文串的最小修改次数
        vector<vector<int>> f(k,vector<int>(n,INT_MAX));
        //当k=0时,表示不划分时,也就是整个字符串为回文串所需要修改的时间。
        for(int i=0;i<n;i++){
            f[0][i]=v[0][i];
        }
        //当k>0时
        for(int ans=1;ans<k;ans++){
        	//i:第ans次切割后的最后一个区间的右端点
            for(int i=ans;i<n;i++){
            	//j:第ans次切割后的最后一个区间的左端点
                for(int j=i;j>=ans;j--)
                //获得最优值:将区间[0,i]划分ans次,得到ans+1个字符串,且均为回文串的最小次数。
                f[ans][i]=min(f[ans][i],f[ans-1][j-1]+v[j][i]);
            }
        }
        return f[k-1][n-1];
    }
};

JAVA版本:

class Solution {
    int n=0;
    int[][] v;
    void dp1(char[] s){
        for(int lens=2;lens<=n;lens++){
            for(int i=0;i+lens-1<n;i++){
                int j=i+lens-1;
                v[i][j]=v[i+1][j-1]+(s[i]!=s[j] ? 1:0);
            }
        }
    }
    void dp2(char[] s){
        for(int i=n-2;i>=0;i--){
            for(int j=i+1;j<n;j++){
                v[i][j]=v[i+1][j-1]+(s[i]!=s[j] ? 1:0);
            }
        }
    }
    public int palindromePartition(String s, int k) {
        n=s.length();
        v = new int[n][n];
        char[] c=s.toCharArray();
        dp1(c);
        //dp2(c);
        int[][] f = new int[k][n];
        for(int[] x:f){
            Arrays.fill(x,Integer.MAX_VALUE);
        }
        for(int i=0;i<n;i++){
            f[0][i]=v[0][i];
        }
        for(int ans=1;ans<k;ans++){
            for(int i=ans;i<n;i++){
                for(int j=i;j>=ans;j--)
                f[ans][i]=Math.min(f[ans][i],f[ans-1][j-1]+v[j][i]);
            }
        }
        return f[k-1][n-1];
    }
}
;