例子只有四位数,却有81种组合方式,题目规定最长可以为12位数字,则有531441种组合方式,把每一种组合通过查找词典库进行匹配,这样的效率是无法忍受的(尽管查词典时可以用Binary Search),所以必须另谋出路。
我们倒过来想一想,反正字母和数字的映射关系是固定的,是否可以把词典中的词翻译成数字,然后直接进行数字的比较,而又因为词典已经是升序排列了,这样只需从头到尾遍历一次,就可以找出所有的可能了。
原来我是打算把数字作为字符串存储的,然后用库函数进行比较,比如GREG转换成字符串“4734”,不过我觉得每次都进行字符串的匹配不一定有进行整数的比较效率高,虽然在求整数时用了乘法。(关于这一点,以后有时间在求证一下,也希望大牛给些建议。。。)
由于是12为数字,超过了int表示的范围,所以要用long long声明,读取数据要用"%lld",这里WA了一次,杯具!
/* ID: LANG: C TASK: namenum */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 5000 #define L 14 typedef struct { char name[L]; long long num;//avoid overflow }Word; int getIndex(char c) { switch(c) { case 'A': case 'B': case 'C': return 2; case 'D': case 'E': case 'F': return 3; case 'G': case 'H': case 'I': return 4; case 'J': case 'K': case 'L': return 5; case 'M': case 'N': case 'O': return 6; case 'P': case 'R': case 'S': return 7; case 'T': case 'U': case 'V': return 8; case 'W': case 'X': case 'Y': return 9; } return -1; } int main() { FILE *fin = fopen("namenum.in", "r"); FILE *fout = fopen("namenum.out", "w"); FILE *fdict = fopen("dict.txt", "r"); int i, j, n, len; long long one; Word words[N]; i = 0; while(fgets(words[i].name, L, fdict) != NULL) { len = strlen(words[i].name); words[i].num = getIndex(words[i].name[0]); for(j = 1; j < len - 1; j++) { // cause name[len-1] is '/n' words[i].num = words[i].num * 10 + getIndex(words[i].name[j]); } i++; } n = i; j = 0; fscanf(fin, "%lld", &one);//5747867437 will overflow if one is the type of int for(i = 0; i < n; i++) { if(one == words[i].num) { j++; fprintf(fout, "%s", words[i].name); } } if(j == 0) fprintf(fout, "NONE/n"); exit(0); }
分析的解法一:使用二分查找的方法,对输入数字每一个对应的字符进行定位,找到这个字符出现位置的上下界,然后对下一个字符进行定界,递归进行直到最后一个字符,然后对界内的所有名字和找到的名字进行匹配,输出结果。这种方法分析中说容易出错(“A single off-by-one error would doom a program in a contest”),我没有尝试,不过看上去确实挺复杂的,让我写的话,调试的时间都可能比编码的时间长!冏
分析的解法二:非常之简短!利用的hash的思想,声明一个字符数组,然后赋值
map['A'] = map['B'] = map['C'] = '2';
map['D'] = map['E'] = map['F'] = '3';
遍历时拿出每一个word,对每一个名字中的字符找到相应的映射数字和输入的数字进行比较,比我的方法有快了一大步,不需要求什么整数值或者转换成字符串值,非常之高效!
唯一需要注意的地方是scanf产生没有'/n'的字符串,输出word时自己加上。。。
看来学过的东西都还给老师了,拿来题没有一点儿感觉,这怎么行?!!