题目链接: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;
}