hdu 1298 字典树 + DFS (模拟T9文本输入)

题意:
      给你一些按键顺序,让你输出每一步中概率最大的那个单词,这里的概率计算方
法好好看看别弄错了,一开始就是因为弄错了,各种wa,比如 abc 1 ,ab 1,那么
ab 的概率就是2 ,而不是4,一开始我误认为是所有单词累加后再把每个单词的每个字母累加作为当前单词的概率的,结果各种wa。

思路:
      先建一颗字典树,为了是节省内存,方便更新,和快速查询,其实hash也可以

,不过我自己一般都是用map去hasn,目测这个题目map去hash会TLE,因为要设计到拆串和各种mark,map是排序的,说远了,建树的时候记得更新概率值,然后就是暴力深搜,把每一个长度的都找出来,然后开个数组更新当前的最有和记录答案串,深搜的时候a,b,c...这样自然就是字典序.


#include<stdio.h>
#include<string.h>
#include<stdlib.h>

typedef struct Tree
{
    Tree *next[26];
    int v;
}Tree;

Tree root;
char now[111] ,ans_str[222][111];
int max[111] ,Key[111];
int jianzi[8] = {3 ,3 ,3 ,3 ,3 ,4 ,3 ,4};

char mk[8][4] =
{'a' ,'b' ,'c' ,'0' ,'d' ,'e' ,'f' ,'0',
 'g' ,'h' ,'i' ,'0' ,'j' ,'k' ,'l' ,'0',
 'm' ,'n' ,'o' ,'0' ,'p' ,'q' ,'r' ,'s',
 't' ,'u' ,'v' ,'0' ,'w' ,'x' ,'y' ,'z'};


void Buid_Tree(char *str ,int vv)
{
    int len = strlen(str);
    Tree *p = &root ,*q;
    for(int i = 0 ;i < len ;i ++)
    {
       int id = str[i] - 'a';
       if(p -> next[id] == NULL)
       {
           q = (Tree *) malloc(sizeof(root));
           q -> v = vv;
           for(int j = 0 ;j < 26 ;j ++)
           q -> next[j] = NULL;
           p -> next[id] = q;
           p = p -> next[id];
       }
       else
       {
          p = p -> next[id];
          p -> v += vv;
       }
    }
}

int Find(char *str)
{
    int len = strlen(str);
    Tree *p = &root;
    int sum = 0;
    for(int i = 0 ;i < len ;i ++)
    {
       int id = str[i] - 'a';
       p = p -> next[id];
       if(p == NULL) return -1;
       sum += p -> v;
    }
    return p -> v;
}

void DFS(int ii ,int n)
{
    if(ii == n + 1) return;
    for(int i = 0 ;i < jianzi[Key[ii] - 2] ;i ++)
    {
       now[ii-1] = mk[Key[ii] -2][i];
       now[ii] = '\0';
       int sum = Find(now);
       if(sum == -1) continue;
       if(sum > max[ii])
       {
           max[ii] = sum;
           for(int j = 0 ;j <= ii ;j ++)
           ans_str[ii][j] = now[j];
       }
       DFS(ii + 1 ,n);
     }
}




int main ()
{
    int t ,n ,m ,i ,vv ,cas = 1;
    char str[111];
    scanf("%d" ,&t);
    while(t--)
    {
       for(i = 0 ;i < 26 ;i ++)
       root.next[i] = NULL;
       scanf("%d" ,&n);
       while(n--)
       {
         scanf("%s %d" ,str ,&vv);
         Buid_Tree(str ,vv);
       }
       scanf("%d" ,&m);
       printf("Scenario #%d:\n" ,cas ++);
       while(m--)
       {
           memset(max ,255 ,sizeof(max));
           scanf("%s" ,str);
           int len = strlen(str);
           int last = str[len-1] - '0';
           for(i = 0 ,len --;i < len ;i ++)
           Key[i+1] = str[i] - '0';
           DFS(1 ,len);
           for(i = 1 ;i <= len ;i ++)
           if(max[i] == -1) puts("MANUALLY");
           else puts(ans_str[i]);
           puts("");
       }
       puts("");
    }
    return 0;
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值