UVALive 6133_Cellphone Typing题解
题意:N个单词的字典,求这N个的单词的平均敲击键盘的次数,也就是敲击键盘总数/N个单词。
1、每个单词的第一个字母必须敲击
2、如果一个字母的子节点超过一个或者,该字母为某个单词的结束字母,则下一个字母也要敲击一次。也就是说前一个字母决定下一个字母是否需要敲击
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<map> #include<cmath> using namespace std; struct Trie //字典树结构 { Trie *child[26]; int num; //子节点数 bool end; //判断该字母是否为某个单词的结束字母 Trie() //构造函数 { num=0; end=0; memset(child,0,sizeof(child)); } }; Trie *root,*s,*lrelia; void Create(char *str) //插入单词 { s=root; int i=0; while(str[i]) { int id=str[i]-'a'; if(s->child[id]==0) //如果该字母还没有出现在字典中 { s->child[id]=new Trie; s->num++; //子节点数+1 s=s->child[id]; } else { s=s->child[id]; } i++; } s->end=1;//标记单词的最后一个字母 } double Search(char *str) { s=root; double len=1; //因为第一个字母必须得敲击,所以len赋值1, int o=strlen(str); /* 既然前一个字母的子节点数决定下一个字母是否要敲击, 我们只需要遍历第1个到len-1个字母就可以了。 */ for(int i=0;i<o-1;++i) { int id=str[i]-'a'; s=s->child[id]; if(s->num>1||s->end==1) len++; } return len; } char a[100002][90]; int main() { int n; while(~scanf("%d",&n)) { root=new Trie; //重新初始化字典树 for(int i=0;i<n;++i) { scanf("%s",a[i]); Create(a[i]); } double l=0;//所有单词的敲击总长度 for(int i=0;i<n;++i) l+=Search(a[i]); //每个单词单加的结果。 printf("%.2lf\n",l/n);//总长度除以n个单词 } return 0; }