题意:简便使用手机9键输入英文单词,给你一个字典以及字典中每个单词出现的可能性,按单词出现的可能性,在你按下某些键的组合时,自动给你调出最可能出现的单词。输入:首先输入一个数t,表示有t组测试案列,然后再输入一个数w(0<=w<=1000)表示接下来有w行输入,每行首先输入一个由小写字母组成的字符串(长度不超过100),然后再空一格,输入一个数p,表示出现这个字符串的可能性。
值得注意的是:可能性是可以累加的。
比如输入:hell 3
hello 4
idea 8
next 8
super 3
那么你输入435561时就会依次出现 i id hel hell hello,然若把那个hell 3 改成hell 5 那么就会出现 h he hel hell hello ...
解题思路基本就是:字典树+DFS,先依据输入的字典建立一个字典树,然后再依据输入的数字,从字典树中搜索每一种组合,找到可能性最大的那一种就行。
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
#define MAXN 150000
string T[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
struct Trie
{
int next[26];
int p;
}tr[MAXN];
int maxp=-1;
string str,ans;
void CreateTrie(string s,int m,int &k)
{
int num,cur=0;
for(unsigned i=0;i<s.length();i++)
{
num=s[i]-'a';
if(!tr[cur].next[num])
{
tr[cur].next[num]=k;
cur=k++;
tr[cur].p=m;
}
else
{
cur=tr[cur].next[num];
tr[cur].p+=m;
}
}
}
void DFS(string tt,int cur,int x,int cnt)
{
//cout<<tt<<endl;
if(cur==x)
{
if(maxp<tr[cnt].p)
{
maxp=tr[cnt].p;
ans=tt;
}
return ;
}
int k=str[cur+1]-'0';
unsigned l=T[k].length();
for(unsigned i=0;i<l;i++)
{
if(tr[cnt].next[T[k][i]-'a'])
{
string temp=tt;
temp+=T[k][i];
int tcnt=tr[cnt].next[T[k][i]-'a'];
DFS(temp,cur+1,x,tcnt);
}
}
}
int main()
{
int t,n,p,ca=1;
cin>>t;
while(t--)
{
memset(tr,0,sizeof(tr));
cin>>n;
string s;
int i,k=1;
for(i=0;i<n;i++)
{
cin>>s>>p;
CreateTrie(s,p,k);
}
cin>>n;
cout<<"Scenario #"<<ca++<<":"<<endl;
for(i=0;i<n;i++)
{
cin>>str;
//string tt="";
for(unsigned j=0;j<str.length()-1;j++)
{
maxp=0;
DFS("",-1,j,0);
if(maxp) cout<<ans<<endl;
else cout<<"MANUALLY"<<endl;
}
cout<<endl;
}
cout<<endl;
}
return 0;
}