建立字典树,对输入的每组数字,每一个数字进行一次深搜,详细见注释。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXL = 105;
struct trieNode //字典树结点
{
int p; //频率
trieNode* next[26];
trieNode()
{
p = 0;
for (int i = 0; i < 26; i++)
next[i] = NULL;
}
};
trieNode* root; //根结点
int keyboard[8][4] = { {0,1,2},{3,4,5},{6,7,8},{9,10,11},{12,13,14},
{15,16,17,18},{19,20,21},{22,23,24,25} }; //手机键盘
int num[8] = { 3,3,3,3,3,4,3,4 }; //手机键盘各按键包含的字母数量
char c[MAXL]; //输入的一串数字
int q; //查找路径上的最大频率
char ans[MAXL], output[MAXL]; //查找结果
//向字典树中插入单词s
void insert(char* s, int k)
{
trieNode* r = root; //从根结点开始寻找
for (int i = 0; s[i]; i++)
{
int x = s[i] - 'a';
if (r->next[x] == NULL)
r->next[x] = new(trieNode);
r = r->next[x];
r->p += k; //单词路径上所有字母的频率加上该单词的频率
}
}
//深搜,查找输入数字对应的频率最高的单词
//r为目前指针位置,k为目前查找到第几个数字,len为输入数字的长度
void dfs(trieNode* r, int k, int len)
{
if (k == len) //递归出口
{
if (r->p > q)
{
q = r->p;
for (int i = 0; i < k; i++)
output[i] = ans[i] + 'a';
output[k] = '\0';
}
return;
}
int x = c[k] - '2'; //当前的输入数字
for (int i = 0; i < num[x]; i++) //依次查找该数字对应的所有字母
{
int t = keyboard[x][i];
if (r->next[t])
{
ans[k] = t;
dfs(r->next[t], k + 1, len);
ans[k] = 0;
}
}
}
//删除字典树
void del(trieNode* head)
{
for (int i = 0; i < 26; i++)
{
if (head->next[i])
del(head->next[i]);
}
delete(head);
}
int main()
{
int t; //测试用例的数量
int w, p, m;
char s[MAXL]; //输入的单词
int Case = 1; //当前测试用例
scanf("%d", &t);
while (t--)
{
root = new(trieNode); //建立字典树
scanf("%d", &w); //字典中单词的数量
for (int i = 0; i < w; i++) //输入单词及频率
{
scanf("%s%d", s, &p);
insert(s, p);
}
printf("Scenario #%d:\n", Case++);
scanf("%d", &m); //测试的组数
for (int i = 0; i < m; i++)
{
scanf("%s", c);
int len = strlen(c) - 1;
for (int i = 0; i < len; i++)
{
q = 0;
dfs(root, 0, i + 1);
if (q)
printf("%s\n", output);
else
printf("MANUALLY\n");
}
printf("\n");
}
printf("\n");
del(root);
}
return 0;
}
继续加油。