(HDU)1298 (POJ)1451 - T9 【字典树】+【DFS】

全网最详细 解决戴维南定理的详细推导 替代定理,戴维南定理详细证明 阅读详情

T9

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 2852    Accepted Submission(s): 1068


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 entered by pressing one key several times. For example, if you wanted to type "hello" you had to press key 4 twice, key 3 twice, key 5 three times, again key 5 three times, and finally key 6 three times. This procedure is very tedious and keeps many people from using the Short Message Service.

This led manufacturers of mobile phones to try and find an easier way to enter text on a mobile phone. The solution they developed is called T9 text input. The "9" in the name means that you can enter almost arbitrary words with just nine keys and without pressing them more than once per character. The idea of the solution is that you simply start typing the keys without repetition, and the software uses a built-in dictionary to look for the "most probable" word matching the input. For example, to enter "hello" you simply press keys 4, 3, 5, 5, and 6 once. Of course, this could also be the input for the word "gdjjm", but since this is no sensible English word, it can safely be ignored. By ruling out all other "improbable" solutions and only taking proper English words into account, this method can speed up writing of short messages considerably. Of course, if the word is not in the dictionary (like a name) then it has to be typed in manually using key repetition again.


Figure 8: The Number-keys of a mobile phone.


More precisely, with every character typed, the phone will show the most probable combination of characters it has found up to that point. Let us assume that the phone knows about the words "idea" and "hello", with "idea" occurring more often. Pressing the keys 4, 3, 5, 5, and 6, one after the other, the phone offers you "i", "id", then switches to "hel", "hell", and finally shows "hello".

Write an implementation of the T9 text input which offers the most probable character combination after every keystroke. The probability of a character combination is defined to be the sum of the probabilities of all words in the dictionary that begin with this character combination. For example, if the dictionary contains three words "hell", "hello", and "hellfire", the probability of the character combination "hell" is the sum of the probabilities of these words. If some combinations have the same probability, your program is to select the first one in alphabetic order. The user should also be able to type the beginning of words. For example, if the word "hello" is in the dictionary, the user can also enter the word "he" by pressing the keys 4 and 3 even if this word is not listed in the dictionary.
 

Input
The first line contains the number of scenarios.

Each scenario begins with a line containing the number w of distinct words in the dictionary (0<=w<=1000). These words are given in the next w lines. (They are not guaranteed in ascending alphabetic order, although it's a dictionary.) Every line starts with the word which is a sequence of lowercase letters from the alphabet without whitespace, followed by a space and an integer p, 1<=p<=100, representing the probability of that word. No word will contain more than 100 letters.

Following the dictionary, there is a line containing a single integer m. Next follow m lines, each consisting of a sequence of at most 100 decimal digits 2-9, followed by a single 1 meaning "next word".
 

Output
The output for each scenario begins with a line containing "Scenario #i:", where i is the number of the scenario starting at 1.

For every number sequence s of the scenario, print one line for every keystroke stored in s, except for the 1 at the end. In this line, print the most probable word prefix defined by the probabilities in the dictionary and the T9 selection rules explained above. Whenever none of the words in the dictionary match the given number sequence, print "MANUALLY" instead of a prefix.

Terminate the output for every number sequence with a blank line, and print an additional blank line at the end of every scenario.
 

Sample Input
2 5 hell 3 hello 4 idea 8 next 8 super 3 2 435561 43321 7 another 5 contest 6 follow 3 give 13 integer 6 new 14 program 4 5 77647261 6391 4681 26684371 77771
 

Sample Output
Scenario #1: i id hel hell hello i id ide idea Scenario #2: p pr pro prog progr progra program n ne new g in int c co con cont anoth anothe another p pr MANUALLY MANUALLY
 
题意:模拟手机输入法的记忆性,你以前输入过的单词会优先出现。(9宫格输入)
输入:第一行输入n,表示有n组数据。每组数据第一行为一个数w,在接下来w行,每行有一个字符串s和数字p(空格隔开),表示该字符串的输入次数。接下来一行为数字m,在接下来m行,每行是一串数字,表示模拟手机在9宫格输入法的按键。(1表示结束)
输出:问每次按键可能出现的字符串,按使用频率高的输出,若没有则输出MANUALLY。

分析:这题用字典树将字符串插入后,如何使得按键满足出现过的字符串呢?我们考虑第一个样例串,按下前两个数字的时候依次是i、id,按下第三个数字的时候,id前缀的字符串已经无法继续匹配了。那么程序需要回过头去需找满足输入的字符串,由于先后顺序,i在h的前面,所以之前没有显示h、he,而是显示i、id,直到id前缀串无法再匹配,出现的是hel、hell。这里面就体现了DFS(深度优先搜索)的思想,所以我们的代码需要用这样的方式来写。

这题蛮坑爹的,输出格式需要注意。以及储存九宫格键位的小技巧,在dfs函数里面体现到位。
我用的是数组字典树
#include <bits/stdc++.h>

using namespace std;

int key[10]={0,0,3,3,3,3,3,4,3,4};    //表示按键i有几个字符
int tot,n,w,p,m,kase=0;               //变量命名按照题述
char s[110];
string out;
int outLen;                           //这个变量单独为out字符串服务
char ch[10][5]={"","","abc","def",
             "ghi", "jkl","mno",
             "pqrs","tuv","wxyz"};    // 九宫格

struct node
{
    int next[26];
    int cnt;
    void init()
    {
        cnt=0;
        memset(next,-1,sizeof(next));
    }
}T[1000000];

void insert(char* s,int n)
{
    int i,p=0,len=strlen(s);
    for(i=0;i<len;i++)
    {
        int x=s[i]-'a';
        if(T[p].next[x]==-1)
        {
            T[tot].init();
            T[p].next[x]=tot++;
        }
        p=T[p].next[x];
        T[p].cnt+=n;
    }
}

void dfs(int i,int len,int p,string a)
{
    if(i==len && T[p].cnt>outLen)   //dfs终止条件,a字符串达到要求长度
    {
        outLen=T[p].cnt;
        out=a;
    }
    int x=s[i]-'0';                 //这里的x对应的是key字典
    for(int j=0;j<key[x];j++)
    {
        int y=ch[x][j]-'a';
        if(T[p].next[y]!=-1)            //如果有出现过的字母
            dfs(i+1,len,T[p].next[y],a+ch[x][j]);
    }
}

void search(char* s)
{
    int i,len=strlen(s);
    for(i=1;i<len;i++)       //按键for循环,按下i个键,出现长度为i的字符
    {
        outLen=0;
        dfs(0,i,0,"\0");
        if(outLen) cout<<out<<endl;
        else printf("MANUALLY\n");
    }
    printf("\n");
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("test.txt","r",stdin);
    freopen("test.out","w",stdout);
    #endif // ONLINE_JUDGE

    for(scanf("%d",&n);n;n--)
    {
        printf("Scenario #%d:\n",++kase);
        T[0].init(); tot=1;    //初始化字典树,类似于清空内存
        scanf("%d",&w);
        for(int i=0;i<w;i++)
        {
            scanf("%s %d",s,&p);
            insert(s,p);
        }
        scanf("%d",&m);
        for(int i=0;i<m;i++)
        {
            scanf("%s",s);
            search(s);
        }
        printf("\n");
    }
    return 0;
}



指针字典树+DFS写法
#include<iostream>  
#include<cstdio>  
#include<cstdlib>  
#include<cstring>  
#include<string>  
#include<queue>  
#include<algorithm>  
#include<map>  
#include<iomanip>  
#define INF 99999999  
using namespace std;  
  
const int MAX=100+10;  
int m[10]={0,0,3,3,3,3,3,4,3,4};//表示按键i有几个字符  
char ch[10][5]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};   
char s[MAX];  
string temp;  
int sum;  
  
struct TrieNode{  
    int num;//出现频率  
    TrieNode *next[26];  
    TrieNode(){  
        num=0;  
        memset(next,0,sizeof next);  
    }   
}root;  
  
void InsertNode(char *a,int num){  
    int k=0;  
    TrieNode *p=&root;  
    while(a[k]){  
        if(!p->next[a[k]-'a'])p->next[a[k]-'a']=new TrieNode;  
        p=p->next[a[k++]-'a'];  
        p->num+=num;  
    }  
}  
  
void SearchTrie(int k,int len,TrieNode *p,string a){  
    if(k == len){  
        if(p->num > sum){  
            sum=p->num;  
            temp=a;  
        }  
    }  
    int t=s[k]-'0';  
    for(int i=0;i<m[t];++i){  
        if(p->next[ch[t][i]-'a'])SearchTrie(k+1,len,p->next[ch[t][i]-'a'],a+ch[t][i]);  
    }  
}  
  
void Free(TrieNode *p){  
    for(int i=0;i<26;++i)if(p->next[i])Free(p->next[i]);  
    delete p;  
}  
  
int main(){  
    int t,n,num=0,w;  
    cin>>t;  
    while(t--){  
        cout<<"Scenario #"<<++num<<":\n";  
        cin>>n;  
        for(int i=0;i<n;++i){  
            cin>>s>>w;  
            InsertNode(s,w);  
        }  
        cin>>n;  
        for(int i=0;i<n;++i){  
            cin>>s;  
            int len=strlen(s);  
            for(int j=1;j<len;++j){  
                sum=0;  
                SearchTrie(0,j,&root,"\0");  
                if(sum)cout<<temp<<endl;  
                else cout<<"MANUALLY"<<endl;  
            }  
            cout<<endl;  
        }  
        cout<<endl;  
        for(int i=0;i<26;++i){  
            if(root.next[i])Free(root.next[i]);  
            root.next[i]=NULL;  
        }   
    }  
    return 0;  
}  


电磁炉线圈加热仿真全流程:用Ansys Maxwell分析涡流效应与热损耗 本文详细介绍了使用Ansys Maxwell进行电磁炉线圈加热仿真的全流程。通过构建2D轴对称涡流场模型,深入分析了高频下的涡流效应、趋肤效应与热损耗分布,为优化线圈设计、提升加热效率与均匀性提供了量化依据和实用指南。 阅读详情

相关推荐

保姆级避坑指南:在Ubuntu 22.04上用ROS2 Humble搞定TurtleBot3的SLAM与导航(附5个常见报错解决方案)

本文提供了一份详细的Ubuntu 22.04上使用ROS2 Humble和TurtleBot3进行SLAM建图与导航的避坑指南,涵盖Gazebo启动失败、场景加载问题、环境变量设置、GLIBCXX版本冲突及Nav2参数配置等5个常见报错的解决方案,帮助开发者高效完成机器人导航项目。

weixin_29062823的博客 285

S - T9

Time Limit: 1000MS   Memory Limit: 10000KB   64bit IO Format: %I64d & %I64u [Submit]   [Go Back]   [Status] Description

mr_lee 728

OS实验xv6 6.S081 开坑

OS实验xv6 6.S081 开坑 终于把xv6 2019 6.S081做完了,网络部分没有写,因为有计网实验了。怎么说呢,xv6的坑有点多,能做完多亏了:和我同学ljj交流,参考RedemptionC老哥的博客(他写的非常详细,遗憾的是,他好像没有写mmap),再者就是参考这位老哥的做法(没有源码,写得不是特别详细,不过有借鉴作用,mmap就是借鉴了他的思想)……废话不多说了,直接开始。 实验指导 首推RedemptionC的博客 这位老哥的个人博客 xv6 6.S081官网(后面的实验都要参考官网

不定期更新系统使用、编程小技巧,哔哩哔哩账号:https://space.bilibili.com/399455629,欢迎关注 4493

字典树,字典树+dfs,(数组实现),两个例题

啊哈

qq_24471135的博客 785

绕开华为通道,获取解锁码解锁BootLoader

刷机有风险,操作需谨慎,如果因为各种因素导致手机变砖无法开机,本教程概不负责,望悉知 前言 这篇文章的大多内容是根据我自己找的一篇文章《绕开华为通道,获取解锁码解锁BootLoader》来编写的,里面的大部分内容是文章的原内容。下面的都是我参考文章中做了一些小部分的修改,增加了我华为P8手机的一些操作,下面开始讲述我的解锁过程。 因为华为官方在2018年的七八月份吧,关闭了解锁码的申请通道,这...

Martin.Mu `s Special Column 5万+

Halcon实战:5分钟搞定线序颜色检测(附完整代码解析)

本文详细介绍了如何使用Halcon在5分钟内实现工业级线序颜色检测的高效方案。通过机器视觉技术,结合实战项目经验,提供完整的代码解析和优化技巧,帮助开发者快速构建鲁棒性强、准确率高的检测系统,适用于电子制造和汽车线束等行业。

weixin_29098367的博客 441

Poj 1451 JAVA 个人解题报告

AC 时间 334ms,内存 3000k 题目大意: 模拟手机键盘的九宫格输入模式,每当输入单词,就会显示可能的单词, 根据每个单词的可能性。 这个可能性就是输入列表里跟随每个单词后面的那个正整数。 单词前缀一致的情况下,可能性可以叠加,且只在公用的前缀的字符上叠加, 分支的字符是保持原样的。 按照一定顺序的数字输入, 输出所有可能性的组合。 解题思路: 和前缀有关,字典树是

qq_28052721的博客 331

告别ZotFile!Zotero 7+百度网盘文献同步全攻略(含软链接避坑指南)

本文针对Zotero 7用户,提供了告别ZotFile插件后,利用百度网盘实现文献附件同步的完整解决方案。详细讲解了如何通过设置Zotero链接目录与创建软链接,将附件库迁移至云盘,并附有详细的避坑指南,确保数据安全与多设备同步的稳定性。

mmm90的博客 586

POJ 1451 T9 G++ trie树 dfs

#include <iostream> #include <cstdio> #include <string> using namespace std; //英语 看博友分析 trie树 dfs struct nod{ int sum; int p[26]; }da[10000]; int js; int mp[26]={2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9...

woniupengpeng的专栏 485

Aurix TC3XX Cache memory分析

Aurix Cache memory 分析

qwe0405080615的博客 4346

Vue3 - Arco Design Vue 表格组件 table 隐藏鼠标移入时 hover 高亮背景色,el-table 组件去除鼠标悬停在表格行的 hover 高亮效果(改变鼠标移入时的背景色)

vue3,arcodesignvue,arcodesign,表格,a-table,hover,表格hover的class类名是什么,class,hover,在arcodesignvue项目中,表格组件如何去掉鼠标移入时的hover效果,vue3arco.design表格组件修改鼠标移入行的背景颜色,table表格,取消表格行row移入高亮效果,去掉鼠标移入行时的hover效果,取消a-table的hover状态,取消高亮显示,隐藏表格鼠标hover效果,去除鼠标触摸变色效果,如何取消arco表

🏆 前端领域优质创作者 3771

字典树Trie树 + 深度优先遍历DFS

字典树是非常藏剑的数据结构,一定要学会使用。 这个时一定要学会手写的代码!!!!! C++版本如下: class TrieNode { public: // Initialize your data structure here. TrieNode *child[26]; bool isWord; TrieNode() : isWord(false) ...

JackZhangNJU的专栏 3262

YOLOv4目标检测算法——通俗易懂的解析

YOLOv4目标检测算法——通俗易懂的解析

chase 7135

poj 1451 || hdu 1298 T9

一道模拟手机输入法的题目,输入每个单词以及出现的频率,最后给你一串中

Enmity_Dark 870

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

T9 poj 1451 hdu 1298

题意:就是让你模拟手机输入单词。具体就是给你一些单词,以及该单词被使用的频数,这个频数也是该单词前缀的使用频数,当然不同的单词有可能有相同的前缀,那么这个相同的前缀的使用频数就是这两个单词使用频数之和,以此类推。然后再给你一些数字串,让你针对该数字串的每一个前缀输出它的最有可能对应的单词(即频数最大的字符串)。 题解:字典树+深搜。对输入的字符串建立字典树每个节点中存储相应的前缀的使用频数...

weixin_30372371的博客 125

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

字典树题目总结

Trie 就好比维护了一个字典,可以在这个字典里插入删除字符串,也可以查询一个字符串是否在字典中。Trie的插入查找删除复杂度都是O(m)的,其中m为待插入串的长度。 Trie的原理是利用字符串集合中字符串的公共前缀来降低时间开销以达到提高效率的目的。 HDU1251-统计难题: 最简单的字典树题,对于字典中的字符串插入后依次回答询问子串个数即可。 解题报告

天亮说晚安 3869

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

字典树题目整合

HDU1251-统计难题: 最简单的字典树题,对于字典中的字符串插入后依次回答询问子串个数即可。 解题报告 HDU1305-Immediate Decodability: 这题要求的是对于一个字典是否满足其中任何一个字符串都不是另一个字符串的子串,所以插入所有串后枚举每个串,看是否所有的串都符合子串个数为1(自身是自身的子串)即可。 HDU

hao_zong_yin的博客 983

POJ 1451 字典树

这题的意思有点类似于一个输入法,就是按了一些键,蹦出单词库中频率最高的那个词汇 首先给出的是单词库,每个单词有一个出现频率。 然后给出的是一些询问,每个询问有一个字符串,代表在手机上按了哪些键,最后以1结束。问进行这些按键的过程中出现的单词分别是哪些。 思路就是字典树了。 以手机的8个键做8个指针来建立字典树。 每个结点存的除了指针外,还有出现频率最高的单词。 建树的时候需要注意,每个...

java开发指南博客 【转载】 241

(POJ) 3682 - King Arthur's Birthday Celebration

亚瑟王掷一枚硬币,概率p正面向上,概率1-p反面朝上,现在亚瑟王要掷k次正面朝上,第i次掷硬币时花费2∗i−1。问:期望要掷多少枚硬币才能达到k次正面朝上,以及达到k次正面朝上时的花费。

Doge 1003

(51nod)1001 - 数组中和等于K的数对

给出一个整数K和一个无序数组A,A的元素为N个互不相同的整数,找出数组A中所有和等于K的数对。例如K = 8,数组A:{-1,6,5,3,4,2,9,0,8},所有和等于8的数对包括(-1,9),(0,8),(2,6),(3,5)。

Doge 967

(51nod)1012 - 最小公倍数LCM

输入2个正整数A,B,求A与B的最小公倍数。

Doge 911

(51nod)1003 - 阶乘后面0的数量

n的阶乘后面有多少个0?6的阶乘 = 1*2*3*4*5*6 = 720,720后面有1个0。

Doge 792

(51nod)1004 - n^n的末位数字

给出一个整数N,输出N^N(N的N次方)的十进制表示的末位数字。

Doge 714

51nod 编程挑战

51nod 题目导航,供自己查询。每个题目链接打开后点击文章内部标题可以跳转至原始题目链接。

Doge 655

(UVA)644 (POJ)1056 (HDU)1305 - Immediate Decodability【字典树】

判断字符串中有没有一个串是另一个串的前缀

Doge 635

(51nod)1002 - 数塔取数问题

一个高度为N的由正整数组成的三角形,从上走到下,求经过的数字和的最大值。 每次只能走到下一层相邻的数上,例如从第3层的6向下走,只能走到第4层的2或9上。 5 8 4 3 6 9 7 2 9 5 例子中的最优方案是:5 + 8 + 6 + 9 = 28

Doge 588
上一篇: (HDU)1247 - Hat’s Words 【字典树】+细心 or【耍流氓大法map】
下一篇: 字典树存在的意义
ACDoge
博客等级 码龄10年 8粉丝 62原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值