卧薪尝胆,厚积薄发。
提高A组模拟 量子纠缠
Date: Sun Aug 19 07:57:30 CST 2018 In Category: NoCategory

Description:

三个操作:加入一个数字串。询问一个字符串是否在字符集中。将串 $A$ 和串 $B$ 互相纠缠,即若 $A+D$ 在信息集中, $B+D$ 也在信息集中。
$一和三操作之和\le2050$ $总操作之和\le10^5$

Solution:

首先发现如果把信息集建成一棵 $trie$ ,那么 $3$ 操作就是把这两个字符串对应的节点合并,即 $A$ 所有的转移 $B$ 也有。问题就变成如何合并两个节点,可以用并查集维护合并,每次把一个的并查集父亲设成另一个,并递归合并所有的转移,如果一个为空那么返回,注意在递归时 $b$ 不能更改,因为 $b$ 的并查集父亲已经改变,如果修改了 $b$ 那 $b$ 的转移就找不到了。每次转移时用并查集祖先的转移。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define MAXL 1000100
int n;
char c[MAXL * 8];
struct node
{
int tr[10];
bool tag;
}t[MAXL];
int ptr = 0;
int newnode(){return ++ptr;}
int root;
int f[MAXL];
int find(int x){return (f[x] == x ? x : f[x] = find(f[x]));}
void insert(char c[])
{
int cur = root;
int l = strlen(c + 1);
for(int i = 1;i <= l;++i)
{
if(t[cur].tr[c[i] - '0'] == 0)
t[cur].tr[c[i] - '0'] = newnode();
cur = find(t[cur].tr[c[i] - '0']);
}
t[cur].tag = true;
return;
}
bool query(char c[])
{
int cur = root;
int l = strlen(c + 1);
for(int i = 1;i <= l;++i)
{
if(t[cur].tr[c[i] - '0'] == 0)
return false;
cur = find(t[cur].tr[c[i] - '0']);
}
return t[cur].tag;
}
int &getnode(char c[])
{
int cur = root;
int l = strlen(c + 1);
for(int i = 1;i < l;++i)
{
if(t[cur].tr[c[i] - '0'] == 0)
t[cur].tr[c[i] - '0'] = newnode();
cur = find(t[cur].tr[c[i] - '0']);
}
return t[cur].tr[c[l] - '0'];
}
void merge(int &a,int &b,bool flag)
{
a = find(a);int y = find(b);
if(a == 0 && y == 0)
{
if(flag)a = b = newnode();
return;
}
if(a == y)return;
if(a == 0){a = y;return;}
if(b == 0){b = a;return;}
f[y] = a;
if(t[y].tag)t[a].tag = true;
for(int i = 0;i < 10;++i)
{
merge(t[a].tr[i],t[y].tr[i],false);
a = find(a);
}
return;
}
void connect()
{
int &a = getnode(c);
scanf("%s",c + 1);
int &b = getnode(c);
merge(a,b,true);
return;
}
int main()
{
freopen("quantum.in","r",stdin);
freopen("quantum.out","w",stdout);
root = newnode();
for(int i = 1;i < MAXL;++i)f[i] = i;
scanf("%d",&n);
int t;
for(int i = 1;i <= n;++i)
{
scanf("%d%s",&t,c + 1);
if(t == 1)insert(c);
if(t == 2)puts(query(c) ? "1" : "0");
if(t == 3)connect();
}
fclose(stdin);
fclose(stdout);
return 0;
}
In tag: 字符串-trie
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡