给定26个1-100表示的非归一化概率,和一个26个小写字母组成的序列,计算使用霍夫曼压缩后,这个序列占用的总比特数。 输入为1行,前面26个数字为小写字母a-z的非归一化概率,然后是一个序列,数字和序列间均以空格隔开。 输出为一个数字,表示这个序列占用的总比特数。 说明:1、压缩后的序列不考虑字节补齐(即不需要变成字节的整倍数) 2、输出:总比特数%100007 范围:概率范围在1-100,字符串长度100000-1000000 写出C语言代码
时间: 2024-03-03 10:49:45 浏览: 116
以下是C语言代码实现:
```c
#include <stdio.h>
#include <stdlib.h>
#define MOD 100007
typedef struct Node {
int freq;
int lchild, rchild;
} Node;
int cmp(const void *a, const void *b) {
return *((int *)a) - *((int *)b);
}
int main() {
int freq[26];
char str[1000005];
scanf("%d", &freq[0]);
for (int i = 1; i < 26; i++) {
scanf("%d", &freq[i]);
}
scanf("%s", str);
int len = 0;
while (str[len] != '\0') len++;
int *arr = (int *)malloc(len * sizeof(int));
for (int i = 0; i < len; i++) {
arr[i] = str[i] - 'a';
}
qsort(arr, len, sizeof(int), cmp);
Node *tree = (Node *)malloc(2 * len * sizeof(Node));
int cnt = len;
for (int i = 0; i < len; i++) {
tree[i].freq = freq[arr[i]];
tree[i].lchild = -1;
tree[i].rchild = -1;
}
while (cnt > 1) {
int min1 = -1, min2 = -1;
for (int i = 0; i < cnt; i++) {
if (tree[i].freq > 0 && (min1 == -1 || tree[i].freq < tree[min1].freq)) {
min2 = min1;
min1 = i;
} else if (tree[i].freq > 0 && (min2 == -1 || tree[i].freq < tree[min2].freq)) {
min2 = i;
}
}
tree[cnt].freq = tree[min1].freq + tree[min2].freq;
tree[cnt].lchild = min1;
tree[cnt].rchild = min2;
tree[min1].freq = -1;
tree[min2].freq = -1;
cnt++;
}
int ans = 0;
for (int i = 0; i < len; i++) {
int cur = arr[i];
int curNode = cnt - 1;
while (tree[curNode].lchild != -1 || tree[curNode].rchild != -1) {
int l = tree[curNode].lchild, r = tree[curNode].rchild;
if (l != -1 && tree[l].freq > 0 && (r == -1 || (tree[r].freq <= 0 || tree[l].freq <= tree[r].freq))) {
ans += 1;
curNode = l;
} else {
ans += 2;
curNode = r;
}
}
ans += 1;
tree[curNode].freq--;
if (tree[curNode].freq == 0) cnt--;
}
printf("%d\n", ans % MOD);
free(arr);
free(tree);
return 0;
}
```
该代码使用霍夫曼树的思想对给定的序列进行压缩,将压缩后的比特数输出。
阅读全文