UVA 12526 Cellphone Typing (字典树)
来源:互联网 发布:魅影传说坐骑进阶数据 编辑:程序博客网 时间:2024/04/30 20:08
UVA 12526 Cellphone Typing (字典树)
Cellphone Typing
64-bit integer IO format: %lld Java class name: Main
[PDF Link]
A research team is developing a new technology to save time when typing text messages in mobile devices. They are working on a new model that has a complete keyboard, so users can type any single letter by pressing the corresponding key. In this way, a user needs P keystrokes to type a word of length P.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:
- The system never guesses the first letter of a word, so the first letter always has to be input manually by pressing the corresponding key.
- If a non-empty succession of letters c1c2...cn has been input, and there is a letter c such that every word in the dictionary which starts with c1c2...cn also starts with c1c2...cnc, then the system inputs c automatically, without the need of a keystroke. Otherwise, the system waits for the user.
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.
Input
Each test case is described using several lines. The first line contains an integer N representing the number of words in the dictionary ( 1N105). Each of the next N lines contains a non-empty string of at most 80 lowercase letters from the English alphabet, representing a word in the dictionary. Within each test case all words are different, and the sum of the lengths of all words is at most 106.Output
For each test case output a line with a rational number representing the average number of keystrokes needed to type a word in the dictionary. The result must be output as a rational number with exactly two digits after the decimal point, rounded if necessary.Sample Input
4hellohellheavengoodbye3hiheh7structurestructuresrideridersstresssolsticeridiculous
Sample Output
2.001.672.71
题意:首先是一个n,表示后面有n行字符串。由小写字母组成然后通过类似于现在的打字,要是遇到相同的字母,后面就马上连下去,比如第一个案例hello,hell,heaven,goodbye,当输入h的时候,由于h开头的字符串有三个,而且第二个都是e,所以e会直接输出,而当再输入一个a的时候,heaven就直接出来了而当输入的不是a,是l的时候,因为hello和hell从第三个开始的相同是hell所以,hell直接出来了。而当第一个输入的是g的时候,因为g的字符串只有一个,所以直接出goodbye所以hello要输入3次hell要输入2次heaven要输入2次goodbye要输入1次答案就是(3+2+2+1)/ 4题解:用字典树来做,字典树是一种哈希树的变种,用来排序,储存,统计字符串,当然不单单是字符串它是用结构体来储存的,然后通过结构体中的next[]来表示后面接着什么字符。它是用公共前缀放在一起,这样就可以节省很多的空间。组建树的时候通过将每个字符串末尾进行flag标记为-1(如hell和hello中,在hell后面的l这里,要标记-1),而且将分叉点也标记为-1(如hello和heaven,中a这里要标记-1),然后当遍历的时候,每遇到一个flag为-1的时候就将那个字符串所需输入的次数加1。要注意,每次的第一个字母,都是要输入的。后面当有分叉的时候,表明分叉的地方有分歧,输入时不会蹦出来,所以也要输入一次,如hello,heaven,但输入h的时候,只会蹦出he,后面的a要在输入当有其它字符串当作前缀的时候,入hell,hello,要输入hello的时候,只会蹦出hell,后面还要自己输入一个o也就只要关注这样三个地方就可以了,要是同时是末尾和分叉,只要加一次就够了,不要两次叠加#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include <algorithm>#include <iostream>using namespace std;#define maxn 200005typedef struct Trie{ //字典树所用到的结构体int flag; //用来标记这个结点是不是末尾,或者分叉点Trie *next[26]; //用了next,就可以不用一个个记录下字符了,可以用第几个来表示,要是小写字母,就是26,要是加上大写字母,就是52,这样类推}Trie;char str[maxn][100]; //存放字符串,用于构造树,和查询遍历的时候用Trie *root; //首个结点void Insert(char *ch){int len = strlen (ch), i, j, temp1 = 0, temp2 = 0;Trie *p = root, *q;for (i = 0; i < len; ++i){int id = ch[i] - 'a'; //表示这个字符属于第几个位置,用位置来表示字符if (p->next[id] == NULL){ //如果到这里开始,后面没有和这个字符串类似的前缀字符了,就开始分叉q = (Trie *) malloc (sizeof (Trie)); //新构建一个结点,来存放开始的分叉if (temp1 == 1 && temp2 == 0){ //这里是用来标记分叉时候的flagp->flag = -1;temp2 = 1;}q->flag = 1;for (j = 0; j < 26; ++j) //新建结点要将next[]都赋值为NULLq->next[j] = NULL;p->next[id] = q;p = q;}else {temp1 = 1; //这里表示相同前缀p = p->next[id];}}p->flag = -1;}int Query(char *ch){ //用来记录每个字符串所需要输入几次int ant = 1, len = strlen (ch), i;Trie *p = root;if (len == 1)return 1;for (i = 0; i < len; ++i){int id = ch[i] - 'a';if (p->next[id]->flag == -1 && i != len - 1) //这里还要注意,不要将自己的末尾当作标记来加1,所以要除去i ==len - 1时的情况ant++;p = p->next[id];}return ant;}int main (){//freopen ("in.txt", "r", stdin);int n, len, i;while (scanf ("%d", &n) != EOF){getchar();root = (Trie *) malloc (sizeof (Trie)); //构建根节点for (i = 0; i < 26; ++i)root->next[i] = NULL;for (i = 1; i <= n; ++i){scanf ("%s", str[i]);Insert(str[i]); //构造字典树}int sum = 0;for (i = 1; i <= n; ++i) //遍历,确定每个字符串要输入几次sum += Query(str[i]);printf ("%.2lf\n", sum * 1.0 / n);}return 0;}/*3aababc2.00*/
- UVA 12526 Cellphone Typing (字典树)
- UVA 12526 Cellphone Typing (字典树)
- UVA - 12526 Cellphone Typing
- UVALive 6133 Cellphone Typing(字典树)
- Cellphone Typing - UVaLive 6133 Trie树
- 6133 Cellphone Typing (trie)
- UVa 11530 - SMS Typing
- typing...
- typing
- UVA 12937 字典树
- uva 11488 字典树
- UVA 11488 字典树
- UVA 12506(字典树)
- UVa 1401 字典树+DP
- UVA 11732 链式字典树
- UVA 11732 - strcmp() Anyone? 字典树
- UVa:1401 Remember the Word(字典树)
- UVA 11732 strcmp() Anyone?(字典树Trie)
- CSDN-MarkDown
- QQ好友列表很炫?其实很简单!
- 第5章
- android引导页的实现
- 泛型(一)
- UVA 12526 Cellphone Typing (字典树)
- (4.1.28.2)HttpPost.setHeader("Cookie", "PHPSESSID=" + PHPSESSID)方式的HttpClient工具类
- 使用laypage分页
- ACdream 1073 雷霆战机
- 函数表达式 和函数声明
- python正则表达式 re (二)findall与finditer
- 来京两周年
- C语言函数参数压栈顺序为何是从右到左?
- MarkDown