题意:
给出一些字符串,统计出现的次数,并按字典序输出。
分析:
裸的Trie树,因为输出按字符串的字典序输出,所以插入的时候,把第一次出现的字符串暂时保存起来。以后排完序在查询输出即可。
不过这题我发现了一个很神奇的地方,因为我刚开始保存字母节点的时候开的数组是26,如果出现大写字母或空格可定会报错!但是我下面开了一个a数组,仍然开26大小的节点数组,居然没报错!!而且AC了QAQ。并不是数据只有小写字母,也有大写字母和空格,但是下面加个a数组就可以,把a数组删了就报错,好神奇啊!
782ms
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxnode=300000+10;
const int N=500000+10;
struct Trie
{
int ch[maxnode][26]; //这个26开小了,因为不只有小写字母,但是在开下面那个a数组居然A了!!可以改大一点
int val[maxnode];
int sz,id;
void clear(){id=1;sz=1;memset(ch[0],0,sizeof(ch[0]));}
int idx(char c){return c-'a';}
bool insert(const char *s)
{
int u=0,n=strlen(s);
for(int i=0;i<n;i++){
int c=idx(s[i]);
if(!ch[u][c]){
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]++;
if(val[u]==1)return true;
return false;
}
int query(string s)
{
int u=0,n=s.size();
for(int i=0;i<n;i++){
int c=idx(s[i]);
u=ch[u][c];
}
return val[u];
}
};
char s[33];
int a[N];//这个删了就报错,好神奇
Trie trie;
int main()
{
// freopen("f.txt","r",stdin);
trie.clear();
vector<string>ans;
int tot=0;
while(gets(s)){
tot++;
if(trie.insert(s)){
ans.push_back(s);
}
}
sort(ans.begin(),ans.end());
for(int i=0;i<ans.size();i++){
cout<<ans[i];printf(" %.4f\n",trie.query(ans[i])*100.0/(1.0*tot));
}
return 0;
}