poj 2418 简单Trie树
题意:
给出一些字符串,统计出现的次数,并按字典序输出。
分析:
裸的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; }