Leetcode_1278. Palindrome Partitioning III_[DP]

题目链接

You are given a string s containing lowercase letters and an integer k. You need to :

  • First, change some characters of s to other lowercase English letters.
  • Then divide s into k non-empty disjoint substrings such that each substring is palindrome.

Return the minimal number of characters that you need to change to divide the string.

 

Example 1:

Input: s = "abc", k = 2
Output: 1
Explanation: You can split the string into "ab" and "c", and change 1 character in "ab" to make it palindrome.

Example 2:

Input: s = "aabbc", k = 3
Output: 0
Explanation: You can split the string into "aa", "bb" and "c", all of them are palindrome.

Example 3:

Input: s = "leetcode", k = 8
Output: 0

 

Constraints:

  • 1 <= k <= s.length <= 100.
  • s only contains lowercase English letters.

解法:

Leetcode_132. Palindrome Partitioning II解法,这道题可以有一个比较清晰的思路。

动态规划:dp[idx][k]表示将s[idx : s.size())这个子串划分为k个非空回文子串最少需要改变的字符数。

递归关系:dp[0][k] = min( f(0,idx-1) + dp[idx][k-1]), for idx in [0, s.size()-1],

其中 f(0,idx-1) == 0 if(s[0,idx-1] is palendrome),else f(0,idx-1) == number of chars that have to change.

需要注意,对于dp[idx][k],如果s.size()-idx < k,那么无论如何也不能将s[idx, s.size()-1]划分为k个回文子串。

class Solution {
public:
    vector<vector<bool>> is_palindrome;
    vector<vector<int>> dp;
    int palindromePartition(string s, int k) {
        int len = s.size();
        is_palindrome = std::move(vector<vector<bool>>(len, vector<bool>(len, false)));
        dp = std::move(vector<vector<int>>(len, vector<int>(k+1, INT_MAX)));
        for(int l=1; l<=len; l++)
            for(int head=0; head+l-1<len; head++){
                int tail = head+l-1;
                if(l == 1)
                    is_palindrome[head][head] = true;
                else if(l == 2)
                    is_palindrome[head][tail] = s[head]==s[tail];
                else
                    is_palindrome[head][tail] = (s[head]==s[tail] && is_palindrome[head+1][tail-1]);
            }

        dfs(s, 0, k);
        return dp[0][k];
    }

    int dfs(string &s, int idx, int k){
        if(idx == s.size())
            return k==0 ? 0 : s.size();
        if(dp[idx][k]<INT_MAX)
            return dp[idx][k];
        int ret = s.size()+1;
        for(int l=1; idx+l-1+k-1<s.size(); l++){
            int behind = dfs(s, idx+l, k-1), use = 0;
            if(!is_palindrome[idx][idx+l-1]){
                for(int head=idx, tail=idx+l-1; head<tail; head++, tail--)
                    use += s[head]!=s[tail] ? 1 : 0;
            }
            ret = min(ret, use+behind);
        }
        return dp[idx][k] = ret;
    }
};

 

posted on 2019-12-03 16:12  JASONlee3  阅读(257)  评论(0编辑  收藏  举报

导航