一、题意
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.
二、题解
题意:
题目大意是,给出一个字符串s和k,k表示将s分为k个子串(不包含空串)。求最少更改几个字符使得这k个子串都为回文字符串。
题解:
动态规划。dp[i][j] 表示将字符串s[0,...,j-1]分为i个子串时最少需要改变的字符个数。那么就可以得到状态转移方程:
dp[i][j] = min(dp[i][j], dp[i-1][k]+ pre[k+1][j-1]) , k = i-1-1, ..... , j-1-1。pre[k+1][j-1]表示将字符串s[k+1,.....,j-1]变为回文字符串所需要更改的最少字符数。(这我也是看题解才明白的,感谢大佬 @xiwuxuewei)
AC代码:
class Solution {
public:
int initFirstRow(int j, string &s){
int ret = 0;
for(int i=0; i<(j)/2; i++){
if(s[i] != s[j-i-1]){
ret ++;
}
}
return ret;
}
int pre(int l, int r, string &s){
string temp = s.substr(l-1, r-l+1);
int ret = initFirstRow(temp.length(), temp);
return ret;
}
int palindromePartition(string s, int k) {
int n = s.length();
vector<vector<int >> dp(k+1, vector<int >(n+1, 999));
for(int j=1; j<=n; j++){
dp[1][j] = initFirstRow(j, s);
}
for(int i=2; i<=k; i++){
for(int j=i; j<=n; j++){
if(j==i){
dp[i][j] = 0;
}else{
for(int k=i-1; k<=j-1; k++){
int temp;
temp = dp[i-1][k] + pre(k+1, j, s);
dp[i][j] = min(dp[i][j], temp);
}
}
}
}
return dp[k][s.length()];
}
};