题目链接:T9
题目大意,对于九键的手机发短信的话,对B要按2按两次,题目要求只按一次,那么如果要发送hello,只需要按43556,但这样肯定会有奇异,题目给每个单词一个概率,例如hello 为5,那么h,he,hel,hell和hello出现的概率都为5。
任给一串数字,求出长度为0到len的概率最大的所有的前缀。
分析
1、利用字符串的公共前缀来进行搜索====>字典树
2、输出概率最大的前缀
对每一个单词,进行dfs(cur+1,p->next[id])进行搜索,存储最大的概率prob和相应的前缀结果
代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
const int maxl = 105;
char d[8][5] = { "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" };
char s1[maxl], ans[maxl], tmp[maxl];
bool tag;
int prob;
struct Trie
{
Trie *next[26];
int v;
}*root;
void creatTrie()
{
root = (Trie*)malloc(sizeof(Trie));
for (int i = 0; i<26; i++)root->next[i] = NULL;
root->v = 0;
}
void Insert(char *s, int k)
{
int len = strlen(s);
Trie *p = root, *q;
for (int i = 0; i<len; i++){
int id = s[i] - 'a';
if (p->next[id] == NULL){
q = (Trie*)malloc(sizeof(Trie));
q->v = k;
for (int j = 0; j<26; j++)q->next[j] = NULL;
p->next[id] = q;
p = p->next[id];
}
else{
p->next[id]->v += k;
p = p->next[id];
}
}
}
void Find(int cur, int len, Trie* p)
{
if (cur == len){
tag = true;
if (p->v>prob){
prob = p->v;
for (int i = 0; i<len; i++)ans[i] = tmp[i];
ans[len] = '\0';
}
return;
}
int pos = s1[cur] - '2';
int slen = strlen(d[pos]);
for (int i = 0; i<slen; i++){
int id = d[pos][i] - 'a';
if (p->next[id] == NULL) continue;
else {
tmp[cur] = d[pos][i];
Find(cur + 1, len, p->next[id]);
}
}
}
int main()
{
//freopen("in.txt", "r", stdin);
int c, sc, num, k, len;
scanf("%d", &sc);
for (int c = 1; c <= sc;c++){
creatTrie();
printf("Scenario #%d:\n", c);
scanf("%d", &num);
while (num--){
scanf("%s %d", s1, &k);
Insert(s1, k);
}
scanf("%d", &num);
while (num--){
scanf("%s", s1);
len = strlen(s1);
for (int i = 1; i<len; i++){
prob = 0;
tag = false;
Find(0, i, root);
if (tag)printf("%s\n", ans);
else printf("MANUALLY\n");
}
printf("\n");
}
printf("\n");
}
return 0;
}