标签:
However, this is not fast enough. The team is going to put together a dictionary of the common words that a user may type. The goal is to reduce the average number of keystrokes needed to type words that are in the dictionary. During the typing of a word, whenever the following letter is uniquely determined, the cellphone system will input it automatically, without the need for a keystroke. To be more precise, the behavior of the cellphone system will be determined by the following rules:
For instance, if the dictionary is composed of the words `hello‘, `hell‘, `heaven‘ and `goodbye‘, and the user presses `h‘, the system will input `e‘ automatically, because every word which starts with `h‘ also starts with `he‘. However, since there are words that start with `hel‘ and with `hea‘, the system now needs to wait for the user. If the user then presses `l‘, obtaining the partial word `hel‘, the system will input a second `l‘ automatically. When it has `hell‘ as input, the system cannot guess, because it is possible that the word is over, or it is also possible that the user may want to press `o‘ to get `hello‘. In this fashion, to type the word `hello‘ the user needs three keystrokes, `hell‘ requires two, and `heaven‘ also requires two, because when the current input is `hea‘ the system can automatically input the remainder of the word by repeatedly applying the second rule. Similarly, the word `goodbye‘ needs just one keystroke, because after pressing the initial `g‘ the system will automatically fill in the entire word. In this example, the average number of keystrokes needed to type a word in the dictionary is then (3 + 2 + 2 + 1)/4 = 2.00.
Your task is, given a dictionary, to calculate the average number of keystrokes needed to type a word in the dictionary with the new cellphone system.
4 hello hell heaven goodbye 3 hi he h 7 structure structures ride riders stress solstice ridiculous
2.00 1.67 2.71
吐槽:有一年没写过字典树了,看以前的代码竟然感到很陌生,更可笑的是指针都不知道怎么用了。真是学得不如忘得快,但是好好看看,就很快懂了。
题目大意:给你n个不重复的字符串,每次敲一个字母,有相同前缀的字母都会自动出来,类似手机输入法。问你打出所有字符串平均需要敲多少下。如第一组样例。
hello 只需要敲3次,一次是h,一次是l,一次是o。 hell只需要敲2次,一次是h,一次是l。heaven需要敲2次,一次是h,一次是a。goodbye需要敲1次,即g。所以全部敲完是8次,平均值是2.00。
解题思路:用字典树模拟过程。我们在每个结点记录重复度rep,该结点下面有多少个分叉cross,是否是字符串结尾flag。对于分叉大于1的结点,我们需要加上该结点的重复度,表示需要在该结点下面的那些不同的字符处敲键盘。如果该结点同时是串尾的话,则需要减1,因为对于当前这个串,不需要在下面多敲一次就已经得到了。对于分叉不大于1的结点,我们判断它是否是串尾,如果是串尾,那么我们只需要加上重复度-1即可。最后加上串的个数n,表示对于每个字串,都需要敲1次最开始的那个字母。
#include<bits/stdc++.h> using namespace std; struct NODE { int rep; int cross; bool flag; NODE *next[26]; }; typedef NODE Trie; NODE *newnode(){ Trie *tmp; tmp= new Trie; for(int i=0;i<26;i++) tmp->next[i]=NULL; tmp->flag=0; tmp->cross=0; tmp->rep=0; return tmp; } void Insert ( Trie *rt, char *s ) { int len = strlen ( s ); int idx; for ( int i = 0; i < len; i++ ) { idx = s[i] - ‘a‘; if(rt->next[idx] == NULL) { rt->next[idx] = newnode() ; rt->cross++; } rt=rt->next[idx]; rt->rep++; } rt->flag=1; } double dfs(Trie *rt){ double ret=0; for(int i=0;i<26;i++){ if(rt->next[i]!=NULL){ ret+=dfs(rt->next[i]); } } if(rt->cross>1){ ret+=rt->rep; if(rt->flag==1){ ret--; } }else if(rt->flag==1){ ret+=rt->rep-1; } delete rt; return ret; } int main() { int n; char str[100]; while ( scanf ( "%d", &n ) != EOF ) { Trie *root; root=newnode(); for ( int i = 0; i < n; i++ ) { scanf ( "%s", str ); Insert ( root, str ); } double ans=dfs(root); printf("%.2lf\n",(n+ans)/n*1.0); } return 0; }
BNU 27847——Cellphone Typing——————【字典树】
标签:
原文地址:http://www.cnblogs.com/chengsheng/p/4712558.html