HDU-1298-T9
http://acm.hdu.edu.cn/showproblem.php?pid=1298
很好的一题,字典树+DFS,思路参考swm8023大牛的
题意是模拟手机输入法,给出几个单词即频度,再给出几个数字串,确定对于给定的一个数字串,每输入一个数字,将显示什么字符
本题的数字串的每一个数字均代表一个字母,而不是平常的手机,多个数字可能代表一个字母,首先可将给出的单词即频度记录到字典树中,对于数字串进行DFS,查找其可能表示的频度最大的字符串
例如 ab 2
bc 3
23
23代表的字符串可能是ad,ae,af,bd,be,bf,cd,ce,cf,逐个搜索,找出频度最大的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
struct node
{
int count;
node *childs[26];
node()
{
count=0;
for(int i=0;i<26;i++)
childs[i]=NULL;
}
};
node *root;
node *current,*newnode;
int p;
char s1[105],s2[105],find[105],ans[105];
char phone[8][4]={{0,1,2},{3,4,5},{6,7,8},{9,10,11},{12,13,14},{15,16,17,18},{19,20,21},{22,23,24,25}};
int num[8]={3,3,3,3,3,4,3,4};
void insert(char *str,int k) //插入字符串和它的频度
{
int i,m;
current=root;
for(i=0;i<strlen(str);i++)
{
m=str[i]-'a';
if(current->childs[m]!=NULL)
{
current=current->childs[m];
(current->count)+=k;
}
else
{
newnode=new node;
(newnode->count)+=k;
current->childs[m]=newnode;
current=newnode;
}
}
}
void dfs(int cur,int len,node *nd)
{
if(cur==len)
{
if(nd->count>p) //找频度最大的
{
p=nd->count;
for(int i=0;i<len;i++)
find[i]=ans[i];
find[len]='\0';
}
return;
}
int t=s2[cur]-'2';
for(int i=0;i<num[t];i++)
{
int r=phone[t][i];
if(nd->childs[r]==NULL)
continue;
ans[cur]='a'+r;
dfs(cur+1,len,nd->childs[r]);
}
return;
}
int main()
{
int i,n,m,t,k,cnt,len;
scanf("%d",&t);
for(k=1;k<=t;k++)
{
printf("Scenario #%d:\n",k);
scanf("%d",&n);
root=new node;
while(n--)
{
scanf("%s %d",s1,&cnt);
insert(s1,cnt);
}
scanf("%d",&m);
while(m--)
{
scanf("%s",s2);
len=strlen(s2);
for(i=1;i<len;i++)
{
p=0; //记录字符出现的频度
dfs(0,i,root);
if(p>0)
printf("%s\n",find);
else
printf("MANUALLY\n");
}
printf("\n");
}
printf("\n");
}
return 0;
}