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;

}

 

 

你可能感兴趣的:(ping)