题目链接:
package D0727;
import java.util.Scanner;
public class HDu2527{
class HFM {
public int w, lChild, rChild, parent;
public HFM(int w) {
this.w = w;
lChild = rChild = parent = -1;
}
}
int len;
HFM[] hfm;
// //从huffman中找出两个最小的权值,并保存小标到m1和m2
int m1, m2;
public void selectMin() {
int minw = Integer.MAX_VALUE;
// 找最小的
for (int i = 0; i < len; i++) {
if (hfm[i].w < minw && hfm[i].parent == -1) {
minw = hfm[i].w;
m1 = i;
}
}
// 找次小的
minw = Integer.MAX_VALUE;
for (int i = 0; i < len; i++) {
if (hfm[i].w < minw && hfm[i].parent == -1 && i != m1) {
minw = hfm[i].w;
m2 = i;
}
}
}
// 构建哈夫曼树
public void buildHFM(int[] w) {
len = w.length;
hfm = new HFM[2 * len - 1];
for (int i = 0; i < len; i++)
hfm[i] = new HFM(w[i]);
for (int i = len; i < 2 * len - 1; i++)
hfm[i] = new HFM(-1);
while (len < hfm.length) {
// 从huffman中选择两个权值最小的节点构建新节点
selectMin();
// 构造新节点
hfm[len].w = hfm[m1].w + hfm[m2].w;
hfm[len].lChild = m1;
hfm[len].rChild = m2;
// 修改m1和m2的父节点
hfm[m1].parent = len;
hfm[m2].parent = len++;
}
}
// 求带权路径长
public int WPL(int[] w) {
int sum = 0;
for (int i = 0; i < w.length; i++) {
int ans = 0;
int p = hfm[i].parent;
while (p != -1) {
ans++;
p = hfm[p].parent;
}
sum += ans * w[i];
}
return sum;
}
public static void main(String[] args) {
HDu2527 hdu = new HDu2527();
Scanner sc = new Scanner(System.in);
int n, m;
String str;
while (sc.hasNext()) {
n = sc.nextInt();
while (n-- > 0) {
m = sc.nextInt();
str = sc.next();
// 处理字符串得到权值
int len = 0;
int[] w;
int index = 0;
for (int i = 0; i < str.length(); i++) {
boolean flag = true;
for (int j = i + 1; j < str.length(); j++) {
if (str.charAt(i) == str.charAt(j)) {
flag = false;
break;
}
}
if (flag)
len++;
}
//考虑只有一种字母的情况
if(len==1){
if(str.length()<=m)System.out.println("yes");
else System.out.println("no");
continue;
}
w = new int[len];
char[] ch = str.toCharArray();
for (int i = 0; i < ch.length; i++) {
if (ch[i] != ' ') {
int wi = 1;
for (int j = i + 1; j < ch.length; j++) {
if (ch[i] == ch[j]) {
wi++;
ch[j] = ' ';
}
}
w[index++] = wi;
}
}
/*for(int i = 0;i<w.length;i++){
System.out.println(w[i]);
}*/
hdu.buildHFM(w);
int sum = hdu.WPL(w);
//System.out.println(sum);
if (sum <= m)
System.out.println("yes");
else
System.out.println("no");
//System.out.println();
}
}
}
}