[trie][并差集] Jzoj P5822 量子纠缠

Description

 

Input

第一行包含一个正整数 m,代表操作数。
接下来 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 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/9494996.html
今日推荐