一个单词a如果通过交换单词中字母的顺序可以得到另外的单词b,那么定义b是a的Anigram,例如单词army和mary互为Anigram。另:相同的2个单词不算Anigram。现在给定一个字典,输入Q个单词,从给出的字典中找出这些单词的Anigram。
输入
第1行:1个数N,表示字典中单词的数量。(1 <= N <= 10000) 第2 - N + 1行,字典中的单词,单词长度 <= 10。 第N + 2行:查询的数量Q。(1 <= Q <= 10000) 第N + 3 - N + Q - 2行:用作查询的单词,单词长度 <= 10。
输出
共Q行,输出Anigram的数量,如果没有输出0。
输入样例
5 add dad bad cad did 3 add cac dda
输出样例
1 0 2
解:通过哈希求相同字母的单词数量,通过树状结构求相同单词,两者之差即可。
1 #include <stdio.h> 2 #include <string.h> 3 #include <malloc.h> 4 5 long long key[10000], ans[10000]; 6 int pri[26] = { 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101 }; 7 char cap = 'a'; 8 9 typedef struct Tree 10 { 11 char alp,end; 12 struct Tree* bro,* son; 13 }tree; 14 15 int main() 16 { 17 int n; 18 while (scanf_s("%d", &n) != EOF) 19 { 20 char word[11]; 21 tree* dict = NULL; 22 for (int i = 0; i < n; ++i) 23 { 24 scanf_s("%s", word, 11); 25 int j = 0, len = strlen(word); 26 key[i] = 1; 27 if (word[0] < 'a') cap = 'A'; 28 for (tree** p = &dict, *ps = dict; j < len; ++j) 29 { 30 key[i] *= pri[word[j] - cap]; 31 if (ps == NULL) 32 { 33 loop1:ps = malloc(sizeof(tree)); 34 ps->alp = word[j]; 35 ps->bro = ps->son = NULL; 36 *p = ps; 37 ps->end = 0; 38 } 39 else 40 { 41 while (ps->alp != word[j]) 42 { 43 p = &(ps->bro); 44 ps = ps->bro; 45 if (ps == NULL) goto loop1; 46 } 47 } 48 if (j == len - 1) ps->end = 1; 49 p = &(ps->son); 50 ps = ps->son; 51 } 52 } 53 int q; 54 scanf_s("%d", &q); 55 for (int i = 0; i < q; ++i) 56 { 57 scanf_s("%s", word, 11); 58 int j = 0, len = strlen(word), s = -1; 59 ans[i] = 1; 60 for (tree* p = dict; j < len; ++j) 61 { 62 ans[i] *= pri[word[j] - cap]; 63 if (s == 0) continue; 64 while (p->alp != word[j]) 65 { 66 p = p->bro; 67 if (p == NULL) 68 { 69 s = 0; 70 break; 71 } 72 } 73 if (j != len - 1 && p == NULL) s = 0; 74 else if (j == len - 1) 75 { 76 if (p != NULL && p->end == 0) 77 s = 0; 78 } 79 else if (p->son == NULL) s = 0; 80 else p = p->son; 81 } 82 for (j = 0; j < n; ++j) 83 { 84 if (key[j] == ans[i]) ++s; 85 } 86 printf("%d\n", s); 87 } 88 } 89 return 0; 90 }