给定一本英语单词词典(每个输入行一个单词,字母都用小写),怎么找出所有的变位词类。例如:“deposit”、“dopiest”、“posited”是同一类变位词。
假如在词典中大约有230000个单词,即使一次简单的变位词比较至少也需要花一微秒的时间,总共需要230000个单词*230000次比较/个单词*1微秒/一次比较=52900*10^6微秒=52900秒=14.7小时。
快速算法:可以采用签名、排序、压缩三个步骤来处理上面的问题。
签名(sign):就是对单词内的字母按字典顺序进行排序,如deposit的签名是deiopst。
排序(sort):对所有的签名按字母顺序进行排序。
压缩(squash):将具有相同的前面进行压缩合并,放一个集合输出。
如下过程:
签名sign和排序的代码如下:
int charcomp(char *x, char *y) { return(*x - *y); } #define WORDMAX 100 int main(void) { char word[WORDMAX], sig[WORDMAX]; while (scanf("%s", word) != EOF) { strcpy(sig, word); qsort(sig, strlen(sig),sizeof(char), charcomp); printf("%s %s\n", sig, word); } return 0; }
压缩合并squash的代码如下:
int main(void) { char word[MAX], sig[MAX], oldsig[MAX]; int linenum = 0; strcpy(oldsig, ""); while (scanf("%s %s", sig, word) != EOF) if (strcmp(oldsig, sig) != 0&& linenum > 0) printf("\n"); strcpy(oldsig, sig); linenum++; printf("%s ", word); } printf("\n"); return 0; }
注:该算法在 230000单词中,总共运行时间为 18 seconds: 其中 4 in sign, 11 in sort and 3 in squash.