Welcome to Subscribe On Youtube
2911. Minimum Changes to Make K Semi-palindromes
Description
Given a string s
and an integer k
, partition s
into k
substrings such that the sum of the number of letter changes required to turn each substring into a semi-palindrome is minimized.
Return an integer denoting the minimum number of letter changes required.
Notes
- A string is a palindrome if it can be read the same way from left to right and right to left.
- A string with a length of
len
is considered a semi-palindrome if there exists a positive integerd
such that1 <= d < len
andlen % d == 0
, and if we take indices that have the same modulo byd
, they form a palindrome. For example,"aa"
,"aba"
,"adbgad"
, and,"abab"
are semi-palindrome and"a"
,"ab"
, and,"abca"
are not. - A substring is a contiguous sequence of characters within a string.
Example 1:
Input: s = "abcac", k = 2 Output: 1 Explanation: We can divide s into substrings "ab" and "cac". The string "cac" is already a semi-palindrome. If we change "ab" to "aa", it becomes a semi-palindrome with d = 1. It can be shown that there is no way to divide the string "abcac" into two semi-palindrome substrings. Therefore, the answer would be at least 1.
Example 2:
Input: s = "abcdef", k = 2 Output: 2 Explanation: We can divide it into substrings "abc" and "def". Each of the substrings "abc" and "def" requires one change to become a semi-palindrome, so we need 2 changes in total to make all substrings semi-palindrome. It can be shown that we cannot divide the given string into two substrings in a way that it would require less than 2 changes.
Example 3:
Input: s = "aabbaa", k = 3 Output: 0 Explanation: We can divide it into substrings "aa", "bb" and "aa". The strings "aa" and "bb" are already semi-palindromes. Thus, the answer is zero.
Constraints:
2 <= s.length <= 200
1 <= k <= s.length / 2
s
consists only of lowercase English letters.
Solutions
Optimization: Preprocessing Divisors List
We can calculate the divisors list for each length, which can save a lot of division operations in the inner loop.
-
class Solution { public int minimumChanges(String s, int k) { int n = s.length(); int[][] g = new int[n + 1][n + 1]; int[][] f = new int[n + 1][k + 1]; final int inf = 1 << 30; for (int i = 0; i <= n; ++i) { Arrays.fill(g[i], inf); Arrays.fill(f[i], inf); } for (int i = 1; i <= n; ++i) { for (int j = i; j <= n; ++j) { int m = j - i + 1; for (int d = 1; d < m; ++d) { if (m % d == 0) { int cnt = 0; for (int l = 0; l < m; ++l) { int r = (m / d - 1 - l / d) * d + l % d; if (l >= r) { break; } if (s.charAt(i - 1 + l) != s.charAt(i - 1 + r)) { ++cnt; } } g[i][j] = Math.min(g[i][j], cnt); } } } } f[0][0] = 0; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= k; ++j) { for (int h = 0; h < i - 1; ++h) { f[i][j] = Math.min(f[i][j], f[h][j - 1] + g[h + 1][i]); } } } return f[n][k]; } }
-
class Solution { public: int minimumChanges(string s, int k) { int n = s.size(); int g[n + 1][n + 1]; int f[n + 1][k + 1]; memset(g, 0x3f, sizeof(g)); memset(f, 0x3f, sizeof(f)); f[0][0] = 0; for (int i = 1; i <= n; ++i) { for (int j = i; j <= n; ++j) { int m = j - i + 1; for (int d = 1; d < m; ++d) { if (m % d == 0) { int cnt = 0; for (int l = 0; l < m; ++l) { int r = (m / d - 1 - l / d) * d + l % d; if (l >= r) { break; } if (s[i - 1 + l] != s[i - 1 + r]) { ++cnt; } } g[i][j] = min(g[i][j], cnt); } } } } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= k; ++j) { for (int h = 0; h < i - 1; ++h) { f[i][j] = min(f[i][j], f[h][j - 1] + g[h + 1][i]); } } } return f[n][k]; } };
-
class Solution: def minimumChanges(self, s: str, k: int) -> int: n = len(s) g = [[inf] * (n + 1) for _ in range(n + 1)] for i in range(1, n + 1): for j in range(i, n + 1): m = j - i + 1 for d in range(1, m): if m % d == 0: cnt = 0 for l in range(m): r = (m // d - 1 - l // d) * d + l % d if l >= r: break if s[i - 1 + l] != s[i - 1 + r]: cnt += 1 g[i][j] = min(g[i][j], cnt) f = [[inf] * (k + 1) for _ in range(n + 1)] f[0][0] = 0 for i in range(1, n + 1): for j in range(1, k + 1): for h in range(i - 1): f[i][j] = min(f[i][j], f[h][j - 1] + g[h + 1][i]) return f[n][k]
-
func minimumChanges(s string, k int) int { n := len(s) g := make([][]int, n+1) f := make([][]int, n+1) const inf int = 1 << 30 for i := range g { g[i] = make([]int, n+1) f[i] = make([]int, k+1) for j := range g[i] { g[i][j] = inf } for j := range f[i] { f[i][j] = inf } } f[0][0] = 0 for i := 1; i <= n; i++ { for j := i; j <= n; j++ { m := j - i + 1 for d := 1; d < m; d++ { if m%d == 0 { cnt := 0 for l := 0; l < m; l++ { r := (m/d-1-l/d)*d + l%d if l >= r { break } if s[i-1+l] != s[i-1+r] { cnt++ } } g[i][j] = min(g[i][j], cnt) } } } } for i := 1; i <= n; i++ { for j := 1; j <= k; j++ { for h := 0; h < i-1; h++ { f[i][j] = min(f[i][j], f[h][j-1]+g[h+1][i]) } } } return f[n][k] }
-
function minimumChanges(s: string, k: number): number { const n = s.length; const g = Array.from({ length: n + 1 }, () => Array.from({ length: n + 1 }, () => Infinity)); const f = Array.from({ length: n + 1 }, () => Array.from({ length: k + 1 }, () => Infinity)); f[0][0] = 0; for (let i = 1; i <= n; ++i) { for (let j = 1; j <= n; ++j) { const m = j - i + 1; for (let d = 1; d < m; ++d) { if (m % d === 0) { let cnt = 0; for (let l = 0; l < m; ++l) { const r = (((m / d) | 0) - 1 - ((l / d) | 0)) * d + (l % d); if (l >= r) { break; } if (s[i - 1 + l] !== s[i - 1 + r]) { ++cnt; } } g[i][j] = Math.min(g[i][j], cnt); } } } } for (let i = 1; i <= n; ++i) { for (let j = 1; j <= k; ++j) { for (let h = 0; h < i - 1; ++h) { f[i][j] = Math.min(f[i][j], f[h][j - 1] + g[h + 1][i]); } } } return f[n][k]; }