还是比较好的一道题,初看觉得很复杂,其实答案还是比较简单的。题目大意是模拟手机输入法,早期手机数字按键只有十个,而英文字母有26个,那么如何打出想打的一个单词呢?于是有人预先准备一个单词库,将一些单词及其频率存入其中,那么随着你按键,会显示出对应的所有字母组合中单词库里频率最高的那个。例如:
有 aaa 3,abc 4,bca 5,那么按2221的过程中会显示的就是:
a
bc
bca
注意,有abc的话,其前缀a,ab也会计算频率。因此a出现的频率是7,所有按一个2时才会显示a。另外,判断一个单词出现频率是否最高,其实只需判断其最后一个字母的出现频率是否最大就行了。其他的像频率相同时输出字典序排列的第一个也是要注意的(其实写程序时不注意到这点也没关系,因为一定会输出第一个)。
代码如下:
#include <cstdio>
#include <stack>
#include <set>
#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <list>
#include <functional>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <string>
#include <map>
#include <iomanip>
#include <cmath>
#define LL long long
#define ULL unsigned long long
#define SZ(x) (int)x.size()
#define MP(a, b) make_pair(a, b)
#define MS(arr, num) memset(arr, num, sizeof(arr))
#define PB push_back
#define F first
#define S second
#define ROP freopen("input.txt", "r", stdin);
#define MID(a, b) (a + ((b - a) >> 1))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define lrt rt << 1
#define rrt rt << 1|1
#define root 1,n,1
#define BitCount(x) __builtin_popcount(x)
#define BitCountll(x) __builtin_popcountll(x)
#define LeftPos(x) 32 - __builtin_clz(x) - 1
#define LeftPosll(x) 64 - __builtin_clzll(x) - 1
const double PI = acos(-1.0);
const int INF = 1e7;
using namespace std;
const double eps = 1e-5;
const int MAXN = 300 + 10;
const int MOD = 1000007;
const double M=1e-8;
const int N=100010;
typedef pair<int, int> pii;
typedef pair<int, string> pis;
const int d[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
int n,m,f,dep;
char key[10][5]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
int num[10]={0,0,3,3,3,3,3,4,3,4};
char s[N],ans[N];
struct node
{
int cnt;
node *next[26];
node () {
cnt=0;
MS(next,NULL);
}
};
class trie
{
public:
node *rt;
trie() { rt=new node; }
void insert(char s[],int k)
{
node *p=rt;
int i=0;
while(s[i]) {
if (p->next[s[i]-'a']==NULL) p->next[s[i]-'a']=new node;
p=p->next[s[i]-'a'];
p->cnt+=k;
i++;
}
}
void find(node *p,char word[],int k)
{
if (k==dep && p->cnt>f) {
ans[0]=word[k]='\0';
strcpy(ans,word);
f=p->cnt;
}
int t=s[k]-'0',i,j;
for (i=0;i<num[t];i++) {
if (p->next[key[t][i]-'a']) {
word[k]=key[t][i];
find(p->next[key[t][i]-'a'],word,k+1);
}
}
}
void dfs(node *p)
{
for (int i=0;i<26;i++) {
if (p->next[i]) {
dfs(p->next[i]);
delete p->next[i];
}
}
}
void del()
{
dfs(rt);
MS(rt->next,NULL);
}
};
int main()
{
int i,j,k,T,K=1;
cin>>T;
char word[N];
trie t;
while(T--)
{
printf("Scenario #%d:\n",K++);
scanf("%d",&n);
for (i=0;i<n;i++) {
scanf("%s%d",s,&k);
t.insert(s,k);
}
scanf("%d",&m);
while(m--) {
scanf("%s",s);
int len=strlen(s);
bool flag=false;
for (i=1;i<=len-1;i++) {
if (flag) { //一个优化而已,因为一旦出现一次MANUALLY,后面不管按什么键也是MANUALLY。
puts("MANUALLY");
continue;
}
dep=i; // 递归层数
f=0; // 频率
t.find(t.rt,word,0);
if (f) puts(ans);
else {
puts("MANUALLY");
flag=true;
}
}
puts("");
}
puts("");
t.del();
}
}