题目: http://poj.org/problem?id=1451
题意:
给定一个数据库,包含每个字符串出现的次数;
对于每一个询问,给定一个数字串(9键拼音),输出键入每个数字时出现概率最大的字符串。
分析:
Trie树+map即可实现。
代码:
#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
using namespace std;
typedef long long llong;
const int tmax=105;
char s[tmax];
int key[30]={2,2,2,3,3,3,4,4,4,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,9,0},a[tmax];
int len,cnt,trie[100005][15];
map<string,int> val[100005];
void init()
{
len=strlen(s);
for(int i=0;i<len;i++)
a[i]=key[s[i]-'a'];
return;
}
void insert(int num)
{
int u=0;
for(int i=0;i<len;i++)
{
if(trie[u][a[i]]==0)
trie[u][a[i]]=++cnt;
u=trie[u][a[i]];
string str(s,i+1);
val[u][str]+=num;
}
return;
}
void search()
{
int u=0;
len=strlen(s);
bool ok=false;
for(int i=0;i<len-1;i++)
{
if(ok)
{
cout<<"MANUALLY"<<endl;
continue;
}
u=trie[u][s[i]-'0'];
if(u==0)
{
cout<<"MANUALLY"<<endl;
ok=true;
}
else
{
string ans=val[u].begin()->first;
int ansnum=val[u].begin()->second;
for(map<string,int>::iterator iter=val[u].begin();iter!=val[u].end();iter++)
if(iter->second>ansnum||(iter->second>ansnum&&ans>iter->first))
{
ans=iter->first;
ansnum=iter->second;
}
cout<<ans<<endl;
}
}
cout<<endl;
return;
}
int main()
{
int T,n,m,num;
scanf("%d",&T);
for(int kase=1;kase<=T;kase++)
{
for(int i=0;i<=cnt;i++)
val[i].clear();
cnt=0;
memset(trie,0,sizeof(trie));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s %d",s,&num);
init();
insert(num);
}
cout<<"Scenario #"<<kase<<":"<<endl;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%s",s);
search();
}
cout<<endl;
}
return 0;
}