Poj 2418 (Trie树的应用)
题目链接:http://poj.org/problem?id=2418
题目大意:
阔叶林是一种植物群落,其中的树木都具有叶子面子很大这一共同特征,多结坚果,冬天会进入休眠状态。美国的温度和气候创造了近百种阔叶物种,如橡树、枫树、樱桃树等等,阔叶树几乎占全美树种的40%左右。另一方面,针叶树(拉丁语称为”锥轴树“,因为其叶子是锥形针状的)在美国也随处可见,如雪松、冷杉、铁杉、红杉等。一般针叶树在家里被用作装饰性的木材。
现自然资源部门使用卫星成像技术,在每一天都编制了一张图像清单,记录了一定范围内的每一颗树,先需要你编程计算每一天记录的树种的”人口结构“。
有多个测例(测例无上限),每个测例中都会给出一张树的清单(由卫星拍摄,以树种名称给出),每一颗树占一行,树名不超过30个字符,其中树会重复出现,不会超过10,000个树种,也不会超过1,000,000棵树,对于每个测例都需要按字典升序给出每种树的树名和其占总数的百分比(截断至4位小数),每种树各占一行。
这道题目算是Trie应用的基本题目吧,词频统计。
这道题目的输出,要按照字典序输出,一开始我打算使用快排的,但好像不太好用,刚好前段时间看到了递归输出。并且在参考其他博客的时候,发现了这个用法,不经感慨,这用法太巧妙了~
代码
@
#include <iostream>
#include <stdio.h>
#include <memory.h>
#include <string>
#include <algorithm>
#include <iomanip>
using namespace std;
int nodenum,sum;
struct Trie_node
{
bool isstr;
int cnt;
char name[40];
Trie_node *branch[95];
}node[3000010];
class Trie
{
public:
Trie_node root;
Trie() { root=node[0];}
void insert(char word[])
{
int i=0;
Trie_node *location=&root;
while(word[i])
{
int t=word[i]-' ';
if(location->branch[t]==NULL)
{
location->branch[t]=&node[nodenum];
node[nodenum].isstr=false;
memset(node[nodenum].branch,NULL,sizeof(node[nodenum].branch));
nodenum++;
}
i++;
location=location->branch[t];
}
if(location->isstr==false)
{
location->isstr=true;
location->cnt=1;
strcpy(location->name,word);
}
else
location->cnt++;
}
};
void dfs(Trie_node *root)
{
Trie_node *p=root;
if(p->isstr)
{
cout<<p->name<<" "<<fixed<<setprecision(4)<<100.0*p->cnt/sum<<endl;
}
for(int i=0;i<95;i++)
{
if(p->branch[i])
dfs(p->branch[i]);
}
}
int main()
{
char name[40];
nodenum=1;
sum=0;
Trie t;
while(gets(name))
{
t.insert(name);
sum++;
}
dfs(&t.root);
}
运行结果
1300K 672MS C++ 1525B
运行时间相对于二叉查找树来说,速度更快。