comments | difficulty | edit_url | rating | source | tags | ||
---|---|---|---|---|---|---|---|
true |
困难 |
2575 |
第 199 场周赛 Q4 |
|
行程长度编码 是一种常用的字符串压缩方法,它将连续的相同字符(重复 2 次或更多次)替换为字符和表示字符计数的数字(行程长度)。例如,用此方法压缩字符串 "aabccc"
,将 "aa"
替换为 "a2"
,"ccc"
替换为` "c3"
。因此压缩后的字符串变为 "a2bc3"
。
注意,本问题中,压缩时没有在单个字符后附加计数 '1'
。
给你一个字符串 s
和一个整数 k
。你需要从字符串 s
中删除最多 k
个字符,以使 s
的行程长度编码长度最小。
请你返回删除最多 k
个字符后,s
行程长度编码的最小长度 。
示例 1:
输入:s = "aaabcccd", k = 2 输出:4 解释:在不删除任何内容的情况下,压缩后的字符串是 "a3bc3d" ,长度为 6 。最优的方案是删除 'b' 和 'd',这样一来,压缩后的字符串为 "a3c3" ,长度是 4 。
示例 2:
输入:s = "aabbaa", k = 2 输出:2 解释:如果删去两个 'b' 字符,那么压缩后的字符串是长度为 2 的 "a4" 。
示例 3:
输入:s = "aaaaaaaaaaa", k = 0 输出:3 解释:由于 k 等于 0 ,不能删去任何字符。压缩后的字符串是 "a11" ,长度为 3 。
提示:
1 <= s.length <= 100
0 <= k <= s.length
s
仅包含小写英文字母
class Solution {
public int getLengthOfOptimalCompression(String s, int k) {
// dp[i][k] := the length of the optimal compression of s[i..n) with at most
// k deletion
dp = new int[s.length()][k + 1];
Arrays.stream(dp).forEach(A -> Arrays.fill(A, K_MAX));
return compression(s, 0, k);
}
private static final int K_MAX = 101;
private int[][] dp;
private int compression(final String s, int i, int k) {
if (k < 0) {
return K_MAX;
}
if (i == s.length() || s.length() - i <= k) {
return 0;
}
if (dp[i][k] != K_MAX) {
return dp[i][k];
}
int maxFreq = 0;
int[] count = new int[128];
// Make letters in s[i..j] be the same.
// Keep the letter that has the maximum frequency in this range and remove
// the other letters.
for (int j = i; j < s.length(); ++j) {
maxFreq = Math.max(maxFreq, ++count[s.charAt(j)]);
dp[i][k] = Math.min(
dp[i][k], getLength(maxFreq) + compression(s, j + 1, k - (j - i + 1 - maxFreq)));
}
return dp[i][k];
}
// Returns the length to compress `maxFreq`.
private int getLength(int maxFreq) {
if (maxFreq == 1) {
return 1; // c
}
if (maxFreq < 10) {
return 2; // [1-9]c
}
if (maxFreq < 100) {
return 3; // [1-9][0-9]c
}
return 4; // [1-9][0-9][0-9]c
}
}