码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 1298 T9 ( 字典树 )

时间:2017-09-28 22:21:26      阅读:214      评论:0      收藏:0      [点我收藏+]

标签:using   产生   eof   alt   频率   family   前缀   rcp   个数   

题意 : 给你 w 个单词以及他们的频率,现在给出模拟 9 键打字的一串数字,要你在其模拟打字的过程中给出不同长度的提示词,出现的提示词应当是之前频率最高的,当然提示词不需要完整的,也可以是 w 个单词出现最多次数的前缀。

 

分析 : 利用字典树存储这 w 个单词,然后给每一个结点的权值赋上其单词出现频率,接下来的工作就简单多了,只要暴力枚举模拟输入的数字键盘可能产生的单词组合,然后保存频率最高的那个即可!

 

技术分享
#include<string.h>
#include<stdio.h>
#include<malloc.h>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
const int maxn = 27;
int tot = 0, n, m;
const int INF = 0x3f3f3f3f;
char mp[][5]{ ///模拟数字键盘,因为是从2开始,所以0和1都赋值上一个‘@‘代表空
    {@,@,@,@,@},
    {@,@,@,@,@},
    {a,b,c,@,@},
    {d,e,f,@,@},
    {g,h,i,@,@},
    {j,k,l,@,@},
    {m,n,o,@,@},
    {p,q,r,s,@},
    {t,u,v,@,@},
    {w,x,y,z,@}
};

struct Trie
{
    Trie *Next[maxn];
    int v;
    inline void init(const int val){
        this->v = val;
        for(int i=0; i<maxn; i++)
            this->Next[i] = NULL;
    }
};
Trie *root;

void CreateTrie(char *str, int val)
{
    int len = strlen(str);
    Trie *p = root, *tmp;
    for(int i=0; i<len; i++){
        int idx = str[i]-a;

        if(p->Next[idx] == NULL){
            tmp = (Trie *)malloc(sizeof(Trie));
            tmp->init(val);
            p->Next[idx] = tmp;
        }else (p->Next[idx]->v) += val;///赋上频率权值

        p = p->Next[idx];
    }
}

inline void DelTrie(Trie *T)
{
    if(T == NULL) return ;
    for(int i=0; i<maxn; i++){
        if(T->Next[i] != NULL)
            DelTrie(T->Next[i]);
    }
    free(T);
    return ;
}

char str[111], ans[111], now[111];
int tmp, MaxVal;

void DFS(int pos, int len, Trie *NOD)
{
    if(pos == len){///递归出口,看看频率是否更优,更新答案
        if(NOD->v > MaxVal){
            strcpy(ans, now);
            MaxVal = NOD->v;
        }
        return ;
    }
    int idx = str[pos]-0;

    for(int i=0; mp[idx][i]!=@; i++){///枚举这个数字建的所有字母,遇到‘@‘结束
        int id = mp[idx][i] - a;
        if(NOD->Next[id]){ ///如果字典树关于这个字母的节点不为空的话,则进一步搜索
            now[pos] = mp[idx][i];///now是保存一下暂时现在构造出来的字符串,以便更新
            now[pos+1] = \0;
            DFS(pos+1, len, NOD->Next[id]);///进一步搜索
        }
    }
}

int main(void)
{
    int nCase;
    scanf("%d", &nCase);
    
    for(int Case=1; Case<=nCase; Case++){
        root = (Trie *)malloc(sizeof(Trie));
        root->init(0);
        scanf("%d", &n);
        int tmpVal;
        for(int i=0; i<n; i++){
            scanf("%s %d", str, &tmpVal);
            CreateTrie(str, tmpVal);
        }
        printf("Scenario #%d:\n", Case);
        scanf("%d", &m);

        for(int i=0; i<m; i++){
            scanf("%s", str);
            int len = strlen(str);

            for(int j=1; j<len; j++){///枚举长度
                MaxVal = -INF;
                DFS(0, j, root);
                if(MaxVal == -INF) puts("MANUALLY");
                else puts(ans);
            }
            puts("");
        }puts("");
        DelTrie(root);
    }
    return 0;
}
View Code

 

HDU 1298 T9 ( 字典树 )

标签:using   产生   eof   alt   频率   family   前缀   rcp   个数   

原文地址:http://www.cnblogs.com/Rubbishes/p/7608802.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!