hdu 1298 T9(字典树+DFS)

题目连接:hdu 1298 T9

题目大意:模拟手机打字的猜想功能,根据概率,每按一个按键,输出可能性最高的串。先给定N个单词,以及频率,

然后是Q次询问,每次询问给定一个按按键的顺序,以1为终止。

解题思路:对单词表建立字典树,每个节点有一个经过的频率,这个频率是根据所有经过该节点的单词频率总和。然后

DFS搜索一遍,将答案保存在ans中。

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int maxn = 100005;
const int maxm = 105;
const int sigma_size = 26;
const char dir[15][10] = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};

struct Tire {
    int sz, g[maxn][sigma_size], val[maxn];

    void init();
    int idx(char ch);
    void insert(char *s, int x);
}T;

int N, Q, c[maxm];
char ans[maxm][maxm], w[maxm], r[maxm];

void dfs (int d, int u) {
    if (d) {
        if (T.val[u] > c[d]) {
            c[d] = T.val[u];
            strncpy(ans[d], r, d);
        }
    }

    if (w[d] == 0 || w[d] == ‘1‘)
        return;

    int x = w[d] - ‘0‘;
    for (int i = 0; dir[x][i]; i++) {
        int v = dir[x][i] - ‘a‘;
        if (T.g[u][v] == 0)
            continue;
        r[d] = dir[x][i];
        dfs(d + 1, T.g[u][v]);
    }
}

int main () {
    int cas;
    scanf("%d", &cas);
    for (int kcas = 1; kcas <= cas; kcas++) {
        T.init();
        scanf("%d", &N);

        int x;
        for (int i = 0; i < N; i++) {
            scanf("%s%d", w, &x);
            T.insert(w, x);
        }

        printf("Scenario #%d:\n", kcas);
        scanf("%d", &Q);
        for (int i = 0; i < Q; i++) {
            scanf("%s", w);
            memset(c, 0, sizeof(c));

            dfs(0, 0);
            for (int x = 1; w[x-1] != ‘1‘; x++) {
    //            printf("<%c> %d:", w[x], c[x]);
                if (c[x] == 0)
                    printf("MANUALLY\n");
                else {
                    for (int j = 0; j < x; j++)
                        printf("%c", ans[x][j]);
                    printf("\n");
                }
            }
            printf("\n");
        }
        printf("\n");
    }
    return 0;
}

void Tire::init() {
    sz = 1;
    val[0] = 0;
    memset(g[0], 0, sizeof(g[0]));
}

int Tire::idx(char ch) {
    return ch - ‘a‘;
}

void Tire::insert(char* s, int x) {
    int u = 0, n = strlen(s);
    for (int i = 0; i < n; i++) {
        int v = idx(s[i]);

        if (g[u][v] == 0) {
            g[u][v] = sz;
            memset(g[sz], 0, sizeof(g[sz]));
            val[sz++] = 0;
        }
        u = g[u][v];
        val[u] += x;
    }
}
时间: 2024-10-16 07:52:19

hdu 1298 T9(字典树+DFS)的相关文章

HDU 1298 T9 ( 字典树 )

题意 : 给你 w 个单词以及他们的频率,现在给出模拟 9 键打字的一串数字,要你在其模拟打字的过程中给出不同长度的提示词,出现的提示词应当是之前频率最高的,当然提示词不需要完整的,也可以是 w 个单词出现最多次数的前缀. 分析 : 利用字典树存储这 w 个单词,然后给每一个结点的权值赋上其单词出现频率,接下来的工作就简单多了,只要暴力枚举模拟输入的数字键盘可能产生的单词组合,然后保存频率最高的那个即可! #include<string.h> #include<stdio.h> #

hdu1298 T9(手机输入法,每按一个数字,找出出现频率最高的字串,字典树+DFS)

Problem Description A while ago it was quite cumbersome to create a message for the Short Message Service (SMS) on a mobile phone. This was because you only have nine keys and the alphabet has more than nine letters, so most characters could only be

hdu 2846 Repository 字典树

// hdu 2846 Repository 字典树 // // 题目大意: // // 有n个字符串,m个待询问的字符串,问这些字符串里面以该询问的 // 字符串为子串的字符串有多少个 // // 解题思路: // // 字典树,将字符串的所有子串插入到字典树中,并设立一个No.标识 // 以免重计数.最后查询就好了 // // 感悟: // // 这题的数据量有点大,虽然p是10000,但是长度是20,单个字符串的 // 最大子串数粗略的估计是 20 * 20 ,所以开的空间也要比较大.开始

hdu1247Hat’s Words (组合单词,字典树+DFS)

Problem Description A hat's word is a word in the dictionary that is the concatenation of exactly two other words in the dictionary. You are to find all the hat's words in a dictionary. Input Standard input consists of a number of lowercase words, on

hdu 1298 T9

字典树+DFS. #include<cstdio> #include<cstring> #include<cmath> #include<string> #include<algorithm> using namespace std; struct shu{ int value, nn[27]; }node[250010]; int n, q, i, ii, v, zz, tott, anss, tt, ttt; const int INF =

HDU 1247 简单字典树

Hat’s Words Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7359    Accepted Submission(s): 2661 Problem Description A hat’s word is a word in the dictionary that is the concatenation of exactly

POJ 1451 T9 字典树+优先队列

题目来源:POJ 1451 T9 题意:给你一些单词 和优先值 然后当你按下数字的时候首先会出现哪个单词 就是我们平时手机的按键 思路:建一颗字典树 因为按一个数字对应多个字母 那么就有多种情况 我们要输出权值最大的一个 我用了优先队列 这里每个前缀的优先值是所有单词优先值的和 例如abc 5 abd 6 acd 7 那么a这个前缀的优先值是18 ab的优先值是11 #include <cstdio> #include <cstring> #include <queue>

HDU 2846 Repository(字典树,标记)

题目 字典树,注意初始化的位置~!!位置放错,永远也到不了终点了org.... 我是用数组模拟的字典树,这就要注意内存开多少了,,要开的不大不小刚刚好真的不容易啊.... 我用了val来标记是否是同一个串分解而来的,保存的是串的编号 num记录数目. //string &replace(iterator first0, iterator last0,const_iterator first, const_iterator last); //把[first0,last0)之间的部分替换成[firs

HDU 1298 T9(字典树+dfs)

http://acm.hdu.edu.cn/showproblem.php?pid=1298 题意:模拟手机9键,给出每个单词的使用频率.现在给出按键的顺序,问每次按键后首字是什么(也就是要概率最大的). 思路: 先建立字典树算出每个前缀出现的概率,然后dfs每种情况,选择概率大的. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int