URAL->1002. Phone Numbers
题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1002
写的比较疼的一个题。做法是trie+dp,dp很裸,不是难点。主要是对于trie不太会的同学写起来比较费劲。算是trie的入门题吧。
解法之一就是先把主串转换成字符串,在把字典按照对应的数字转换,插入到trie中。然后对主串每个位置枚举,如果从i+1开始长j的字串存在于字典中,则d[i+j]=min(d[i+j],d[i]+1),剩下来就很好写了。
有一个需要注意的地方就是题目说可能存在多个解求出人一个均可,如果是test3 wa了就注意下这个地方。
#include <iostream> #include <cmath> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; struct trie{ trie *next[26]; int index; }; inline trie *newnode(){ trie *t; t=(trie*)malloc(sizeof(trie)); memset(t,0,sizeof(trie)); t->index=-1; return t; } void insert(trie *s, char x[], int pos){ int i; trie *t; for(i=0; x[i]; i++){ if(s->next[x[i]-'a'])s=s->next[x[i]-'a']; else{ t=newnode(); s->next[x[i]-'a']=t; s=t; } } s->index=pos; } void del_trie(trie * s){ int i; for(i=0; i < 26 ;i++){ if(s->next[i]) del_trie(s->next[i]); } free(s); s=NULL; } int find(trie *s, char x[]){ int i; if(x[0] == 0) return -1; for(i=0; x[i]; i++){ if(s->next[x[i]-'a'])s=s->next[x[i]-'a']; else break; } if(x[i]==0)return s->index; else return -1; } char str[120], dict[50005][60]; char change[30]; /* 1 ij 2 abc 3 def 4 gh 5 kl 6 mn 7 prs 8 tuv 9 wxy 0 oqz */ void init(){ change[0]=change[1]=change[2]='c'; change[3]=change[4]=change[5]='d'; change[6]=change[7]='e'; change[8]=change[9]='b'; change[10]=change[11]='f'; change[12]=change[13]='g'; change[15]=change[17]=change[18]='h'; change[19]=change[20]=change[21]='i'; change[22]=change[23]=change[24]='j'; change[14]=change[16]=change[25]='a'; } int d[120], v[120]; int main(){ int n, i, j, max_len, l, length; init(); char temp[60]; while (scanf("%s", str)!=EOF){ if (!strcmp(str, "-1"))break; length = strlen(str); for (i=0; i<length; i++) str[i]=char(str[i]-'0'+'a'); trie *T=newnode(); scanf("%d", &n); max_len=0; for (i=0; i<n; i++){ scanf("%s", dict[i]); l=strlen(dict[i]); max_len=max(max_len, l); for (j=0; j<l; j++) temp[j]=change[dict[i][j]-'a']; temp[j]='\0'; insert(T, temp, i); } memset(d, -1, sizeof(d)); d[0] = 0; for (i=0; i<=length; i++) if (d[i] > -1){ memset(temp, '\0', sizeof(temp)); for (j=1; j<=max_len; j++){ if (i+j > length)break; temp[j-1]=str[i+j-1]; int t=find(T, temp); if (t > -1){ if (d[i+j]==-1 ||d[i+j] > d[i]+1){ d[i+j] = d[i]+1; v[i+j] = t; } } } } if (d[length]==-1)printf("No solution.\n"); else { int p[100], k=0, now=d[length], j = length; p[k++]=v[length]; for (i=length-1; i>= 1; i--){ if (d[i] == now-1 && j-i==strlen(dict[v[j]])){ p[k++]=v[i]; now=d[i]; j=i; } } for (i = k-1; i>=0; i--){ printf("%s", dict[p[i]]); if (i>0)printf(" "); } printf("\n"); } del_trie(T); } return 0; }