import java.util.*;
/**
* NC187 压缩字符串(二)
* @author d3y1
*/
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param s string字符串
* @param k int整型
* @return int整型
*/
public int compressString (String s, int k) {
return solution(s, k);
}
/**
* 动态规划
*
* dp[i][j]表示字符串前i个字符删除j个字符后的最小压缩长度 , j<=k&&j<=i
*
* dp[0][0] = 0
*
* same: 从第i个字符依次向左统计 与第i个字符相同的个数
* diff: 从第i个字符依次向左统计 与第i个字符不同的个数(将被删除)
*
* step 1
* dp[i][j] = dp[i-1][j-1] , j>0
* step 2
* dp[i][j] = Math.min(dp[i][j], dp[m-1][j-diff]+calculate(same)) , 0<m<=i && diff<=j
*
* i: 0 1 2 3 4 5 6 7 8 9
* s: a a b a a a c c c
* k=0 0 1 2 3 4 5 5 6 7 7
* k=1 0 1 2 2 2 2 3 4 4
* k=2 0 1 2 2 2 2 3 4
* k=3 0 1 2 2 2 2 3
*
* @param s
* @param k
* @return
*/
private int solution(String s, int k){
int n = s.length();
int[][] dp = new int[n+1][k+1];
// init
for(int i=0; i<=n; i++){
// >>1 防止溢出
Arrays.fill(dp[i], Integer.MAX_VALUE>>1);
}
dp[0][0] = 0;
for(int i=1; i<=n; i++){
for(int j=0; j<=k&&j<=i; j++){
if(j > 0){
dp[i][j] = dp[i-1][j-1];
}
// 从第i个字符依次向左统计 与第i个字符相同的个数
int same = 0;
// 从第i个字符依次向左统计 与第i个字符不同的个数
int diff = 0;
for(int m=i; 0<m&&diff<=j; m--){
if(s.charAt(m-1) == s.charAt(i-1)){
same++;
dp[i][j] = Math.min(dp[i][j], dp[m-1][j-diff]+calculate(same));
}else{
diff++;
}
}
}
}
return dp[n][k];
}
/**
* 计算压缩后的长度
* @param same 相同字符长度
* @return
*/
private int calculate(int same){
if(same == 1){
return 1;
}
if(same < 10){
return 2;
}
if(same < 100){
return 3;
}
return 4;
}
}