Description
Input
第一行包含一个正整数 m,代表操作数。
接下来 m 行,每行可能有以下形式:
1 s 代表将数字串 s 加入信息集中
2 s 代表询问数字串 s 是否在信息集中
3 a b 代表使数字串 a 和 b 互相纠缠
接下来 m 行,每行可能有以下形式:
1 s 代表将数字串 s 加入信息集中
2 s 代表询问数字串 s 是否在信息集中
3 a b 代表使数字串 a 和 b 互相纠缠
Output
对于每一个 2 操作,如果询问串不在集合中,请输出一行一个整数 0,否则输出一行一个整 数 1。
Sample Input
11 1 123 2 123 2 0 3 12 13 1 124 2 133 2 134 2 13 3 1 11 2 111 2 11111111111111111111111124
Sample Output
1 0 1 1 0 0 1
Data Constraint
题解
- 如果没有操作三,那就是一棵裸trie了
- 考虑第三操作,纠缠按照题目意思就是A有的后缀B也要有
- 实际上,其实就是把A和B变成一个点了
- 我们在Trie上找到A,B对应的节点,然后可以把其中一个点的fa设为另一个点
- 然后继续往子树去做,有公共点就继续上面的操作
- 否则,如果有一条边连向c,而另一个点没有到c的边,就可以把另一个点连到c
- 就是递归合并上述字典树上的两个节点
代码
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 int trie[8000010][10],fa[8000010],stop[8000010],tot=1,m; 7 char s[8000010],s1[8000010]; 8 int getfather(int x) { return fa[x]==x?x:fa[x]=getfather(fa[x]); } 9 void insert(char *s) 10 { 11 int len=strlen(s+1),p=1; 12 for (int i=1;i<=len;i++) 13 { 14 int ch=s[i]-'0'; 15 if (!trie[p][ch]) trie[p][ch]=++tot; 16 p=getfather(trie[p][ch]); 17 } 18 stop[p]++; 19 } 20 int &get(char *s) 21 { 22 int len=strlen(s+1),p=1; 23 for (int i=1;i<len;i++) 24 { 25 int ch=s[i]-'0'; 26 if (!trie[p][ch]) trie[p][ch]=++tot; 27 p=getfather(trie[p][ch]); 28 } 29 return trie[p][s[len]-'0']; 30 } 31 bool find(char *s) 32 { 33 int len=strlen(s+1),p=1; 34 for (int i=1;i<=len;i++) 35 { 36 int ch=s[i]-'0'; 37 if (!trie[p][ch]) return 0; 38 p=getfather(trie[p][ch]); 39 } 40 if (stop[p]==0) return 0; else return 1; 41 } 42 void together(int &a,int &b,int d) 43 { 44 int u=getfather(a),v=getfather(b); 45 if (u==v&&u==0) 46 { 47 if (d) a=b=++tot; 48 return; 49 } 50 if (u==v) return; 51 if (!a) a=v; 52 else 53 if (!b) b=u; 54 else 55 { 56 fa[v]=u; 57 stop[u]=stop[u]+stop[v]; 58 for (int i=0;i<10;i++) 59 { 60 together(trie[u][i],trie[v][i],0); 61 u=getfather(u); 62 } 63 } 64 } 65 int main() 66 { 67 scanf("%d",&m); 68 for (int i=1;i<=8000000;i++) fa[i]=i; 69 for (int i=1;i<=m;i++) 70 { 71 int d; 72 scanf("%d%s",&d,s+1); 73 if (d==1) insert(s); 74 if (d==2) printf("%d\n",find(s)); 75 if (d==3) 76 { 77 scanf("%s",s1+1); 78 int &a=get(s),&b=get(s1); 79 together(a,b,1); 80 } 81 } 82 return 0; 83 }