1 /*
2 * 并查集+字典树
3 */
4
5 #include <cstdio>
6 #include <cstdlib>
7 #include <cstring>
8 #include <iostream>
9
10 using namespace std;
11
12 const int N = 21;
13 const int M = 200005;
14
15 int cs;
16 int parent[M];
17 char strA[N], strB[N];
18 struct node {
19 int c;
20 node *child[52];
21 node() {
22 c = 0;
23 for (int i=0; i<52; ++i) child[i] = NULL;
24 }
25 }*root;
26
27 int insert(char str[]) {//字典树功能:将名字映射成代表该名字的一个整数
28 node *p = root;
29 int len = strlen(str);
30 for (int k,i=0; i<len; ++i, p=p->child[k]) {
31 if (str[i]>='a' && str[i]<='z') k = str[i] - 'a';
32 else k = str[i] - 'A' + 26;
33 if (!p->child[k]) p->child[k] = new node();
34 // else if (i==len-1 && p->child[k]->c>0) return p->child[k]->c;
35 }
36 if (p->c) return p->c;
37 return p->c = ++cs;
38 }
39
40 void UFset() {
41 for (int i=1; i<M; ++i) parent[i] = -1;
42 }
43
44 int Find(int x) {
45 int s;
46 for (s=x; parent[s]>0; s=parent[s]);
47 while (s != x) {//路径压缩
48 int tmp = parent[x];
49 parent[x] = s;
50 x = tmp;
51 }
52 return s;
53 // if (parent[x] > 0) parent[x] = Find(parent[x]);
54 }
55
56 int Union(int r1, int r2) {
57 int tmp = parent[r1] + parent[r2];
58 if (parent[r1] > parent[r2]) parent[r1] = r2, parent[r2] = tmp;
59 else parent[r2] = r1, parent[r1] = tmp;
60 return tmp;
61 }
62
63 void del(node *p) {
64 for (int i=0; i<52; ++i) {
65 if (p->child[i]) del(p->child[i]);
66 }
67 delete p;
68 p = NULL;
69 }
70
71 int main() {
72 int t;
73 while (scanf ("%d", &t) != EOF) {
74 while (t--) {
75 int n;
76 scanf ("%d", &n);
77 cs = 0;
78 UFset();
79 root = new node();
80 while (n--) {
81 scanf ("%s%s", strA, strB);
82 int a = insert(strA);
83 int b = insert(strB);
84 int r1 = Find(a);
85 int r2 = Find(b);
86 if (r1 != r2) printf ("%d\n", abs(Union(r1, r2)));
87 else printf ("%d\n", abs(parent[r1]));
88 }
89 del(root);
90 }
91 }
92 return 0;
93 }