哈夫曼编码和字典树

简介: 哈夫曼编码和字典树

哈夫曼

HUD2527

http://acm.hdu.edu.cn/showproblem.php?pid=2527

#include<iostream>
#include<string.h>
#include<queue>
using namespace std;
priority_queue <int,vector <int>,greater <int> > q;
int main() {
  int t;
  cin>>t;
  while(t--) {
    int n;
    char ch[100005];
    cin>>n>>ch;
    int tem[26];
    for(int i=0; i<26; i++)tem[i]=0;
    for(int i=0; i<strlen(ch); i++) {
      tem[ch[i]-'a']++;
    }
    int len=0,sum=0;
    for(int i=0; i<26; i++) {
      q.push(tem[i]);
      len++;
    }
    if(len==1){
      sum=q.top();
    }
    else{
      while(q.size()>1){
        int a=q.top();
        q.pop();
        int b=q.top();
        q.pop();
        sum+=a+b;
        q.push(a+b);
      }
    }
    q.pop();
    if(sum>n)
      cout<<"no"<<endl;
    else
      cout<<"yes"<<endl;
  }
}


VJ

http://vjudge.net/contest/view.action?cid=49918#problem/A

#include<iostream>
#include<string.h>
#include<queue>
using namespace std;
priority_queue <int,vector <int>,greater <int> > q;
int main() {
  int n;
  while(cin>>n) {
    int len=1;
    for(int i=0; i<n; i++) {
      long long t;
      cin>>t;
      q.push(t);
      len++;
    }
    long long sum=0;
    if(len==1) {
      sum=q.top();
    } else {
      while(q.size()>1) {
        long long a=q.top();
        q.pop();
        long long b=q.top();
        q.pop();
        sum+=a+b;
        q.push(a+b);
      }
    }
    q.pop();
    cout<<sum<<endl;
  }
}

字典树


HUD2072为例

http://acm.hdu.edu.cn/showproblem.php?pid=2072

#include<iostream>
#include<string.h>
#include<sstream>
using namespace std;
int dict[10005][26];
int vis[10005];
int ans,k;
void insert (string s) {
  int len = s.size();
  int root = 0;
  for (int i = 0; i < len; i++) {
    int index = s[i] - 'a';
    if (!dict[root][index]) {
      dict[root][index] = ++k;
    }
    root = dict[root][index];
  }
  if(!vis[root]){
    vis[root]=1; 
    ans++;
  }
}
int main() {
  string s;
  while(getline(cin,s)) {
    if(s[0]=='#')return 0;
    memset(dict,0,sizeof(dict));
    memset(vis,0,sizeof(vis));
    stringstream ss(s);
    string s1;ans=0;
    while(ss>>s1) {
      insert(s1);//插入一个单词 
    }
    cout<<ans<<endl;
  }
}


HUD1251为例

http://acm.hdu.edu.cn/showproblem.php?pid=1251

#include<iostream>
#include<string>
using namespace std;
int dict[1000005][30];
int vis[1000005];
int ans,k;
void insert (string s) {
  int len = s.size();
  int root = 0;
  for (int i = 0; i < len; i++) {
    int index = s[i] - 'a';
    if (!dict[root][index]) {
      dict[root][index] = ++k;
    }
    root = dict[root][index];
    vis[root]++;//每个子串都赋值为1,则abcd里找a,ab,abc,abcd,
    //对应的vis[root]都有 ,并且重复前缀累加vis值 
  }
}
void find (string s) {
  int root = 0;
  int len = s.size();
  for (int i = 0; i < len; i++) {
    int index = s[i] - 'a';
    if(!dict[root][index]) {//如果bc,找abc的前缀,必然不存在以bc为前缀,
    //此时dict[root][index]没有被insert() 赋值,所有为0,检测到直接cout<<0退出即可 
      cout<<0<<endl;
      return ;
    }
    else {
      root=dict[root][index];
    }
  }
  cout<<vis[root]<<endl;//为前缀的单词的数量
}
int main() {
  string s;
  while(getline(cin,s)) {
    if(s[0]=='\0')break;
    insert(s);
  }
  while(cin>>s) {
    find(s);
  }
}

01字典树

HUD4825

http://acm.hdu.edu.cn/showproblem.php?pid=4825

#include<iostream>
#include<stdio.h>
#include<string.h> 
using namespace std;
int dict[3200005][2];
int vis[3200005];
int ans,k;
int n,m;
void insert (int s) {
  int root = 0;
  for (int i = 31; i>=0; i--) {
    int index = (s>>i) & 1;//从高位到低位,存储该数的二进制编码 
    if (!dict[root][index]) {
      dict[root][index] = ++k;
    }
    root = dict[root][index];
  }
  vis[root]=s;//标记数字s的编码root为s 
}
void find (int s) {
  int root = 0;
  for (int i = 31; i>=0; i--) {
    int index = (s>>i) & 1;//位移出每一位 
    if (dict[root][index^1]) {//因为是异或,101与010匹配,所以优先考虑与当前index互斥的数
      root = dict[root][index^1];
    } 
    else {
      root = dict[root][index];//,如果互斥的分支没有那没办法了  
    }
  }
  cout<<vis[root]<<endl;//最后通过标记输出与哪个数最匹配即可 
}
int main() {
  int t;
  scanf("%d",&t);
  for(int i=1; i<=t; i++) {
    memset(dict,0,sizeof(dict));
    k=0;
    scanf("%d%d",&n,&m);
    for(int j=1; j<=n; j++) {
      int cnt;
      scanf("%d",&cnt);
      insert(cnt);
    }
    cout<<"Case #"<<i<<":"<<endl;
    for(int j=1; j<=m; j++) {
      int cnt;
      scanf("%d",&cnt);
      find(cnt);
    }
  }
}


目录
相关文章
|
自然语言处理 算法 搜索推荐
哈夫曼树与哈夫曼编码
本文主要介绍实现哈夫曼树和哈夫曼编码
216 1
哈夫曼树与哈夫曼编码
|
存储 算法 搜索推荐
哈夫曼树、哈夫曼编码和字典树
哈夫曼树、哈夫曼编码和字典树
160 0
|
存储 机器学习/深度学习 算法
|
存储 算法 Linux
秒懂算法 | 字典树
字典树是一种基础方法,请掌握字典树的静态数组存储方法,它在后缀树、回文树、AC自动机、后缀自动机中都要用到。
158 0
|
存储 算法
详解哈夫曼编码
详解哈夫曼编码
详解哈夫曼编码
|
C++
哈夫曼编码(C++优先队列实现)
哈夫曼编码(C++优先队列实现)
250 0
哈夫曼编码(C++优先队列实现)
|
存储 自然语言处理 算法
字典树详解
字典树,顾名思义,是关于“字典”的一棵树。即:它是对于字典的一种存储方式(所以是一种数据结构而不是算法)。
177 0
字典树详解
哈夫曼树与哈夫曼编码(优先队列)
哈夫曼树与哈夫曼编码(优先队列)
394 0
哈夫曼树与哈夫曼编码(优先队列)
|
存储 算法
哈夫曼树、哈夫曼编码详解
哈夫曼树、哈夫曼编码很多人可能听过,但是可能并没有认真学习了解,今天这篇就比较详细的讲一下哈夫曼树。
269 0
哈夫曼树、哈夫曼编码详解