[Trie][并查集]JZOJ 5822 量子纠缠
分析
这道题很容易看出来我们需要把字典树合并,但是对于一个持久的操作,我们无法每次都更新答案,于是想到了并查集。
我们可以用并查集将纠缠的串及其儿子相连,合并,新建等操作,然后查询时也是查询并查集即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <cstring> #define y t[x].c[s[i]-'0'] using namespace std; const int N=1e6+1; struct Node { bool ed; int c[10]; }t[N]; int cnt; int m,f[N]; char s[8*N],s2[8*N]; int Get_F(int x) {return x==f[x]?x:f[x]=Get_F(f[x]);} void Insert(char *s) { int len=strlen(s),x=0; for (int i=0;i<len;i++) y?x=Get_F(y):x=y=++cnt; t[x].ed=1; } bool Search(char *s) { int len=strlen(s),x=0; for (int i=0;i<len;i++) if (y) x=Get_F(y); else return 0; return t[x].ed; } int &Get(char *s) { int len=strlen(s),x=0,i; for (i=0;i<len-1;i++) y?x=Get_F(y):x=y=++cnt; return y; } void Merge(int &s1,int &s2,bool p) { int a=Get_F(s1),b=Get_F(s2); if (!a&&!b) { if (p) s1=s2=++cnt; return; } if (a==b) return; if (!s1) s1=b; else if (!s2) s2=a; else { f[b]=a; t[a].ed|=t[b].ed; for (int i=0;i<10;i++) { Merge(t[a].c[i],t[b].c[i],0); a=Get_F(a); } } } void Stick(char *s1,char *s2) { int &a=Get(s1),&b=Get(s2); Merge(a,b,1); } int main() { freopen("quantum.in","r",stdin); freopen("quantum.out","w",stdout); scanf("%d",&m); for (int i=1;i<=N-1;i++) f[i]=i; while (m--) { int order; scanf("%d%s",&order,&s); if (order==1) Insert(s); if (order==2) printf("%d\n",Search(s)); if (order==3) { scanf("%s",&s2); Stick(s,s2); } } fclose(stdin);fclose(stdout); }
在日渐沉没的世界里,我发现了你。