哈夫曼编码和字典树
哈夫曼
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);
}
}
}