来源:《算法竞赛入门经典》例题5.3.2
题目:输入一个字典(用******结尾),然后再输入若干单词。每输入一个单词w,你都需要在字典中找出所有可以用w的字母重排后得到的单词,并按照字典序从小到大的顺序在一行中输出( 如果不存在,输出:( )。输入单词之间用空格或空行隔开,且所有输入单词都由不超过6个小写字母组成。注意,字典中的单词不一定按字典序排列。
样例输入:
tarp given score refund only trap work earn course pepper part
******
resco nfudre aptr sett oresuc
样例输出:
score
refund
part trap trap
:(
course
分析:
如何判断两个单词是否可以通过重排得到呢?稍微思考就会发现:把两个单词分别按字母顺序排序,然后直接比较即可。同时,原题要求我们把符合条件的单词“按照字典序从小到大的顺序在一行中输出”,这个字典序指的是广义上的标准字典的顺序(按首字母及其后字母进行排序的得到的顺序),并不是我们输入这个字典的顺序,这里往往会引起误会,所以我们在“对单词按字母顺序进行排序”之前要“对字典按单词顺序进行排序”
源码:
#include<stdio.h> #include<stdlib.h> #include<string.h> char word[2000][10],sorted[2000][10]; //word用来保存字典的原始输入 int cmp_char(const void* _a,const void* _b) //字符比较函数 { char* a =(char*)_a; char* b =(char*)_b; return *a - *b; } int cmp_string(const void* _a,const void* _b)//字符串比较函数 { char* a =(char*)_a; char* b =(char*)_b; return strcmp(a,b); } int main() { int i,n=0,found=0; //found为查找成功标志 char w[10]; //w为用户输入字典后需要查找的单词 while(1) //输入字典 { scanf("%s",word[n]); //一个单词一个单词的输入 if(word[n][0] == '*') break; //遇到结束标志就终止循环 n++; //最后一次输入******不计数 } qsort(word,n,sizeof(word[0]),cmp_string);//给字典中所有单词排序(先按首字母,首字母相同按下一个字母,以此类推),即标准字典序 for(i=0;i<n;i++) { strcpy(sorted[i],word[i]); //把经过单词排序的字典word复制到stored qsort(sorted[i],strlen(sorted[i]),sizeof(char),cmp_char);//把sorted中每个单词按字母顺序重排 } while(scanf("%s",w)==1) //持续读取到文件结尾 { qsort(w,strlen(w),sizeof(char),cmp_char);//把输入的单词s也按字母顺序重排 for(i=0;i<n;i++) //循环比较重排后的输入和重排后的字典 if(strcmp(sorted[i],w)==0)//找到 { found=1; printf("%s ",word[i]);//输出原始字典中对应的单词(顺序是标准字典序,即sorted中的顺序,单词是原始字典中的单词,而不是排序后的) } if(!found) printf(":("); printf(" "); } return 0; }