题目大意:
模拟手机T9输入法。先给出n个单词和其出现概率,根据用户按下的数字键,选择相应概率最大的单词输出。
思路:
首先根据给出的单词建树,然后根据按下的数字进行广搜。
代码:
#include<iostream> #include<stdio.h> #include<queue> using namespace std; struct trie //利用结构体来封装字典树的节点。 { trie* next[26]; trie* pre; //指针指向父节点,用于回溯输出单词。 int total; //total用于记录概率。 char letter; trie() //构造函数。 { for(int i=0;i<26;i++) next[i]=NULL; pre=NULL; total=0; letter='\0'; } }; void insert(char* s,int n,trie* root) //将字符串s所表示的单词插入到字典树中。 { trie *p=root; for(int i=0;s[i]!='\0';i++) { if(p->next[s[i]-'a']==NULL) { p->next[s[i]-'a']=new trie; p->next[s[i]-'a']->pre=p; p->next[s[i]-'a']->letter=s[i]; } p=p->next[s[i]-'a']; p->total+=n; } } void output(trie* point) //从point开始回溯至root,输出途径节点的字母,达到输出单词的目的。 { if(point->pre->pre!=NULL) output(point->pre); printf("%c",point->letter); } char T9[10][5]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"}; void bfs(char* num,trie* root) //根据按键广搜 { queue<trie*> q; q.push(root); for(int i=0;num[i]!='1';i++) { int size=q.size(),max=0; //max记录最大概率。 trie* now=NULL; //now指向表示概率最大的词的最后一个字母的节点。 while(size--) { trie *head=q.front(); q.pop(); for(int j=0;j<strlen(T9[num[i]-'0']);j++) //遍历num[i]所表示的几个字母。 { trie *temp=head->next[T9[num[i]-'0'][j]-'a']; if(temp!=NULL) //若树中存在此单词 { if(temp->total>max) { max=temp->total; now=temp; } q.push(temp); } } } if(now==NULL) //now==NULL说明没有单词对应现在的按键序列 printf("MANUALLY"); else output(now); printf("\n"); } printf("\n"); } int main() { int t; scanf("%d",&t); for(int i=1;i<=t;i++) { printf("Scenario #%d:\n",i); trie root; //字典树的根节点。 int w,m; for(scanf("%d",&w);w>0;w--) { char str[101]; int p; scanf("%s%d",str,&p); insert(str,p,&root); } for(scanf("%d",&m);m>0;m--) { char num[101]; scanf("%s",num); bfs(num,&root); //对每个按键序列进行广搜。 } printf("\n"); } }