本题题意比较有意思,大概就是模拟手机输入法,先给你一个用户的词库,即每个单词出现的次数,这个时候再按照九键输入法给你一个数字序列,问你在输入这个序列的过程中,出现的字符串顺序,也就是对于每个数字序列,给出一个最有可能出现的字符串。
首先我们考虑,对于每个数字序列,我们都可以用一个string去映射,这样我们可以用一个map来保存每个数字序列对应的最有可能出现的字符串,可是我们怎么知道每个数字序列最有可能出现的字符串是哪个呢,首先我们对单词进行映射,把每个单词映射成数字序列,然后在插入的过程中,对于每一个前缀都更新一下这个前缀对应的map,最后查询的时候就可以直接输出了。
#include<cstdio>
#include<map>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
using namespace std;
const int maxn = 1e6 + 10;
int tire[maxn][26];
int sum[maxn];
map<string, int> map1;
map<string, string> map2;
int alpha_to_int[30];
int tot;
void init() {
for (int i = 0; i <= 17; ++i)
alpha_to_int[i] = i / 3 + 2;
alpha_to_int[18] = 7;
for (int i = 19; i < 25; ++i)
alpha_to_int[i] = (i - 1) / 3 + 2;
alpha_to_int[25] = 9;
}
void insert(char* s, int num) {
int len = strlen(s);
int rt = 0;
string temp_int = "", temp_alpha = "";
for (int i = 0; i < len; ++i) {
int id = s[i] - ‘a‘;
temp_int += alpha_to_int[id] + ‘0‘;
temp_alpha += id + ‘a‘;
if (tire[rt][id] == 0)
tire[rt][id] = ++tot;
rt = tire[rt][id];
sum[rt] += num;
if (sum[rt] > map1[temp_int]) {
map1[temp_int] = sum[rt];
map2[temp_int] = temp_alpha;
}
}
}
int t, n, num;
char s[110];
int main() {
int cnt = 1;
init();
for (scanf("%d", &t); t; --t) {
map1.clear();
map2.clear();
scanf("%d", &n);
tot = 0;
for (int i = 0; i < n; ++i) {
scanf("%s %d", s, &num);
insert(s, num);
}
scanf("%d", &n);
printf("Scenario #%d:\n", cnt++);
for (int i = 0; i < n; ++i) {
scanf("%s", s);
int len = strlen(s);
string temp = "";
for (int j = 0; j < len - 1; ++j) {
temp += s[j];
if (!map2.count(temp))
printf("MANUALLY\n");
else
printf("%s\n", map2[temp].c_str());
}
printf("\n");
}
printf("\n");
for (int i = 0; i <= tot; ++i) {
sum[i] = 0;
for (int j = 0; j < 26; ++j)
tire[i][j] = 0;
}
}
}
原文:https://www.cnblogs.com/wanshe-li/p/13382190.html