UVALive - 4122 Huffman Code

1 篇文章 0 订阅
1 篇文章 0 订阅

题目大意:

你有一些字符串,它们有各自出现的频率(百分数),分配这些频率使它们的Huffman编码和输入的一样,求可能的方案数。

我们先复习一下Huffman编码:

每次在所有元素中选择两个频率最小的,把它们合并成一个新的元素,其频率是两个频率的总和。新的元素的左子树是两个元素中小的那个,右子树是大的那个。左子树写0,右子树写1。最终拼出来的树,就是Huffman树。从树上往下走,走到的每一个根节点路径上所有的0\1拼起来,就是每个元素的Huffman编码。

更重要的是,Huffman树有一些性质:

对于相同深度的点,左边的频率小于等于右边的频率,这个很显然。这就够了,我们按从小到大的顺序填数,如果是根节点直接填,否则可以算出这个点的频率。加上可行性剪枝,就A掉啦(跑得好慢)

#include<bits/stdc++.h>
#define N 50100
using namespace std;
char sss[N],a[5],b[5];
vector<int> cx[531442];
int len;
inline int gethas(char *c){
	int tot=0;
	for(int i=0;i<strlen(c);i++) tot=tot*27+c[i]-'a'+1;
	return tot;
}
inline void check_min(int &a,int b){if(b<a) a=b;}
map<long long,int> s;
long long base=27*27*27*27;
int main(){
	scanf("%s",sss);len=strlen(sss);
	for(int i=0;i<len;i++){
		int has=0;
		for(int j=0;j+i<len&&j<4;j++){
			has=has*27+sss[i+j]-'a'+1;
			cx[has].push_back(i);
		}
	}
	int q;scanf("%d",&q);
	while(q--){
		scanf("%s%s",a,b);
		int hasa=gethas(a),hasb=gethas(b);
		int ll=strlen(a),rr=strlen(b);
		if(hasa>hasb) swap(hasa,hasb),swap(ll,rr);
		int l=cx[hasa].size(),r=cx[hasb].size();
		int ans=1000086;
		if(l==0||r==0) puts("-1");
		else{
			if(s[hasa*base+hasb]){
				printf("%d\n",s[hasa*base+hasb]);
				continue;
			}
			for(int i=0,now=0;i<l;i++){
				while(cx[hasb][now]<cx[hasa][i]&&now<r) now++;
				if(now!=r) ans=min(ans,(int)max(cx[hasb][now]+rr,cx[hasa][i]+ll)-cx[hasa][i]);
				if(now!=0) ans=min(ans,(int)max(cx[hasb][now-1]+rr,cx[hasa][i]+ll)-cx[hasb][now-1]);
			}
			printf("%d\n",s[hasa*base+hasb]=ans);
		}
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值