UVALive

来源:互联网 发布:mysql pdf 微盘 编辑:程序博客网 时间:2024/06/06 03:10

题目大意:

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

我们先复习一下Huffman编码:

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

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

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

#include<bits/stdc++.h>#define N 50100using 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;}



原创粉丝点击