题意:每组有n个字符串,每个串对应一个权值,给出一个手机按键表,每个数字键可对应按出几个字母,m个询问,给出一串数字(最后一位不计),求该数字串对应的权值最大的字符串(将数字串每个前缀对应的字符串输出);
思路:将n个字符串插入字典树,在串的查询操作上进行深搜以便更新最大值,并且每个数字对应几个字符,分别遍历一下。经典题。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; struct node { int num; node *next[26]; }; node *head; int 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 re[8]={3,3,3,3,3,4,3,4};//一个数字键包含的字母数 void init(node *h) { for(int i=0;i<26;i++) { h->next[i]=NULL; h->num=0; } } int p; char str[500010]; char ch[500010],ans[500010],e[500010]; void h_insert(char s[],int d) { node *t,*s1=head; int n=strlen(s); for(int i=0;i<n;i++) { int k=s[i]-‘a‘; if(s1->next[k]==NULL) { t=new node; init(t); s1->next[k]=t; } s1=s1->next[k]; s1->num+=d; } } void dfs(node *h,int now,int len) { if(now==len) { if(p<h->num)//更新为权值最大的匹配串 { p=h->num; for(int i=0;i<len;i++) e[i]=ans[i]; // e[len]=0;//小技巧 } return; } int t=ch[now]-‘2‘; for(int i=0;i<re[t];i++) { int d=phone[t][i]; if(h->next[d]) { ans[now]=‘a‘+d; dfs(h->next[d],now+1,len); } } return; } int main() { int t,n,i,j,k,m,len,cas; scanf("%d",&t); for(cas=1;cas<=t;cas++) { printf("Scenario #%d:\n",cas); memset(e,0,sizeof(e)); memset(ans,0,sizeof(ans)); memset(str,0,sizeof(str)); memset(ch,0,sizeof(ch)); head=new node; init(head); scanf("%d",&n); while(n--) { scanf("%s %d",str,&k); h_insert(str,k); } scanf("%d",&m); while(m--) { scanf("%s",ch); len=strlen(ch); memset(e,0,sizeof(e)); for(i=1;i<len;i++) { p=0; node *temp=head; dfs(temp,0,i);//枚举前缀,逐个查询 if(p>0) printf("%s\n",e); else printf("MANUALLY\n"); } printf("\n"); } printf("\n"); } return 0; }
时间: 2024-10-07 20:01:25