Cellphone Typing - UVaLive 6133 Trie树

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:
1. The system never guesses the rst letter of a word, so the rst letter always has to be input
manually by pressing the corresponding key.
2. 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 ll 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 rst line contains an integer N representing the
number of words in the dictionary (1 N 105
). 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 di erent, 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
4
hello
hell
heaven
goodbye
3
hi
he
h
7
structure
structures
ride
riders
stress
solstice
ridiculous
Sample Output
2.00
1.67
2.71

题意:给你几个已经存好的字符串,第一个字符需要你去打,如果当前字符串后面的字符只有一种可能的时候,电脑会自动输出下一个字符,除非这个字符串是一个完整的单词。

思路:Trie树,没什么好说的。

AC代码如下:

#include<cstdio>
#include<cstring>
using namespace std;
char s[100010][90];
int num[100010],length[100010],sum;
struct Trie
{ int index,num;
  Trie *next[26];
  Trie()
  { index=-1,num=-1;
    memset(next,0,sizeof(next));
  }
};
void Trie_Insert(Trie *tr,char *s)
{ if(*s!='\0')
  { if(tr->next[*s-'a']==0)
     tr->next[*s-'a']=new Trie;
    Trie_Insert(tr->next[*s-'a'],s+1);
  }
  else
   tr->index=0;
}
void Trie_Search(Trie *tr,int pos,int len)
{ if(tr->num==-1)
  { int i,k=0;
    for(i=0;i<=25;i++)
     if(tr->next[i]!=0)
      k++;
    tr->num=k;
  }
  if( !((tr->index==-1 && tr->num==1) || (tr->index==0 && tr->num==0)) )
   num[pos]++;
  if(len>=length[pos])
  { if(tr->num>0)
     num[pos]--;
    return;
  }
  Trie_Search(tr->next[s[pos][len]-'a'],pos,len+1);
}
int main()
{ int t,n,i,j,k;
  while(~scanf("%d",&n))
  { Trie *root=new Trie;
    for(i=1;i<=n;i++)
    { scanf("%s",s[i]);
      Trie_Insert(root,s[i]);
      length[i]=strlen(s[i]);
    }
    memset(num,0,sizeof(num));
    for(i=1;i<=n;i++)
     Trie_Search(root->next[s[i][0]-'a'],i,1);
    sum=0;
    for(i=1;i<=n;i++)
     sum+=num[i];
    sum+=n;
    printf("%.2f\n",1.0*sum/n);
  }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值