这道题看着很复杂,其实感觉就是建字典树,然后bfs一遍,然后bfs的队列需要用优先队列来维护出现的频率,每当到新的一层的时候,只输出频率最大的那个,然后把所有这一层的都扩展到下一层,以此类推。
同时最后如果在某一层找不到往下走的时候,后边的就直接输出剩余层数的MAMUALLY。
另外,最好优化下各种空间,一开始卡空间,卡着卡着就过去了hhh
AC代码:
#include <string>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int maxn=1e4;
int trie[maxn][26],tot=1;
int fre[maxn];
string hhash[10]={"","next","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
void init()
{
tot=1;
memset(fre,0,sizeof(fre));
memset(trie,0,sizeof(trie));
}
void insert(string str,int f)
{
int len=str.size(),p=1;
for(int k=0;k<len;k++){
int ch=str[k]-'a';
if(trie[p][ch]==0) trie[p][ch]=++tot;
p=trie[p][ch];
fre[p]+=f;
}
}
struct node{
int f;
int level;
int p;
string s;
node (int _f,int _level,int _p,string _s)
{
f=_f;
level=_level;
p=_p;
s=_s;
}
bool operator < (const node& x) const
{
if(level!=x.level) return level>x.level;
return f<x.f;
}
};
void bfs(string s)
{
string ans="";
priority_queue<node> q;
q.push(node(0,0,1,""));
int level=0;
while(!q.empty()){
node temp=q.top();q.pop();
if(temp.level==s.size()) return;
int opt=s[temp.level]-'0';
level=temp.level;
string sopt=hhash[opt];
if(level==0){
for(int i=0;i<sopt.size();i++){
if(trie[temp.p][sopt[i]-'a']!=0)
q.push(node(fre[trie[temp.p][sopt[i]-'a']],temp.level+1,trie[temp.p][sopt[i]-'a'],temp.s+sopt[i]));
}
continue;
}
if(ans.size()<temp.level){
ans=temp.s;
cout<<ans<<endl;
}
for(int i=0;i<sopt.size();i++){
if(trie[temp.p][sopt[i]-'a']!=0)
q.push(node(fre[trie[temp.p][sopt[i]-'a']],temp.level+1,trie[temp.p][sopt[i]-'a'],temp.s+sopt[i]));
}
}
for(int i=level+1;i<s.size();i++)
cout<<"MANUALLY"<<endl;
return;
}
int main()
{
int t;cin>>t;
for(int kcase=1;kcase<=t;kcase++){
int n,m;cin>>n;
init();
for(int i=1;i<=n;i++){
string str;int f;
cin>>str>>f;
insert(str,f);
}
cout<<"Scenario #"<<kcase<<":"<<endl;
cin>>m;
for(int i=1;i<=m;i++){
string s;cin>>s;
bfs(s);
cout<<endl;
}
cout<<endl;
}
}