We first compute the minimum number of changes needed to make any substring a palindrome. Then, we use DP to partition the string into k palindromic substrings with minimal total changes.
classSolution {
public:int palindromePartition(string s, int K) {
int n = s.size();
vector<vector<int>> cost(n, vector<int>(n));
for (int i =0; i < n; ++i)
for (int j = i; j < n; ++j) {
int l = i, r = j, cnt =0;
while (l < r) if (s[l++] != s[r--]) ++cnt;
cost[i][j] = cnt;
}
vector<vector<int>> dp(n+1, vector<int>(K+1, 1e9));
dp[n][0] =0;
for (int i = n-1; i >=0; --i)
for (int k =1; k <= K; ++k)
for (int j = i; j < n; ++j)
dp[i][k] = min(dp[i][k], cost[i][j] + dp[j+1][k-1]);
return dp[0][K];
}
};
classSolution {
publicintpalindromePartition(String s, int K) {
int n = s.length();
int[][] cost =newint[n][n];
for (int i = 0; i < n; ++i)
for (int j = i; j < n; ++j) {
int l = i, r = j, cnt = 0;
while (l < r) if (s.charAt(l++) != s.charAt(r--)) ++cnt;
cost[i][j]= cnt;
}
int[][] dp =newint[n+1][K+1];
for (int[] row : dp) Arrays.fill(row, 1000000000);
dp[n][0]= 0;
for (int i = n-1; i >= 0; --i)
for (int k = 1; k <= K; ++k)
for (int j = i; j < n; ++j)
dp[i][k]= Math.min(dp[i][k], cost[i][j]+ dp[j+1][k-1]);
return dp[0][K];
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
classSolution {
funpalindromePartition(s: String, K: Int): Int {
val n = s.length
val cost = Array(n) { IntArray(n) }
for (i in0 until n)
for (j in i until n) {
var l = i; var r = j; var cnt = 0while (l < r) { if (s[l++] != s[r--]) cnt++ }
cost[i][j] = cnt
}
val dp = Array(n+1) { IntArray(K+1) { 1_000_000_000 } }
dp[n][0] = 0for (i in n-1 downTo 0)
for (k in1..K)
for (j in i until n)
dp[i][k] = minOf(dp[i][k], cost[i][j] + dp[j+1][k-1])
return dp[0][K]
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
classSolution:
defpalindromePartition(self, s: str, K: int) -> int:
n = len(s)
cost = [[0]*n for _ in range(n)]
for i in range(n):
for j in range(i, n):
l, r, cnt = i, j, 0while l < r:
if s[l] != s[r]: cnt +=1 l +=1; r -=1 cost[i][j] = cnt
dp = [[float('inf')] * (K+1) for _ in range(n+1)]
dp[n][0] =0for i in range(n-1, -1, -1):
for k in range(1, K+1):
for j in range(i, n):
dp[i][k] = min(dp[i][k], cost[i][j] + dp[j+1][k-1])
return dp[0][K]
impl Solution {
pubfnpalindrome_partition(s: String, k: i32) -> i32 {
let n = s.len();
let s = s.as_bytes();
letmut cost =vec![vec![0; n]; n];
for i in0..n {
for j in i..n {
let (mut l, mut r, mut cnt) = (i, j, 0);
while l < r {
if s[l] != s[r] { cnt +=1; }
l +=1; r -=1;
}
cost[i][j] = cnt;
}
}
let k = k asusize;
letmut dp =vec![vec![1_000_000_000; k+1]; n+1];
dp[n][0] =0;
for i in (0..n).rev() {
for kk in1..=k {
for j in i..n {
dp[i][kk] = dp[i][kk].min(cost[i][j] + dp[j+1][kk-1]);
}
}
}
dp[0][k]
}
}