BJ模拟:相似子串(树链剖分+hash)
来源:互联网 发布:linux mysql 远程连接 编辑:程序博客网 时间:2024/06/06 13:03
题解:
树上hash值用链剖来维护。
代码:
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<vector>#include<map>using namespace std;typedef long long ll;const int Maxn=4e6+50;const int G=3;inline int read(){ char ch=getchar();int i=0,f=1; while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){i=(i<<3)+(i<<1)+ch-'0';ch=getchar();} return i*f;}int n,tot,fa[Maxn],top[Maxn],dep[Maxn],val[Maxn],idx[Maxn],son[Maxn],sze[Maxn],pos[Maxn],anc[Maxn];struct node{ int to,val; node(int to=0,int val=0):to(to),val(val){}};vector<node>edge[Maxn];map<ll,int>S;ll h1[27][Maxn],h2[27][Maxn],powG[Maxn];inline void Insert(int x,int y,int val){ edge[x].push_back(node(y,val)); edge[y].push_back(node(x,val));}inline void Dfs1(int now,int f=0){ fa[now]=f;dep[now]=dep[f]+1;sze[now]=1; for(int v,e=edge[now].size()-1;e>=0;e--) { v=edge[now][e].to; if(v^f) { Dfs1(v,now); sze[now]+=sze[v]; val[v]=edge[now][e].val; if(sze[son[now]]<sze[v])son[now]=v; } }}inline void Dfs2(int now,int f=0){ if(son[now]) { idx[pos[son[now]]=++tot]=son[now]; top[son[now]]=top[now]; Dfs2(son[now],now); } for(int v,e=edge[now].size()-1;e>=0;e--) { v=edge[now][e].to; if(v^son[now]&&v^f) { idx[pos[v]=++tot]=v; top[v]=v; Dfs2(v,now); } }}inline void SplitTree(){ Dfs1(1); tot=top[1]=idx[1]=pos[1]=1; Dfs2(1);}inline int getf(int i){ if(anc[i]==i)return i; return anc[i]=getf(anc[i]);}inline int Getlca(int x,int y){ while(top[x]^top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); x=fa[top[x]]; } return dep[x]<dep[y]?x:y;}inline int Getlen(int x,int y){ int lca=Getlca(x,y); return dep[x]+dep[y]-2*dep[lca];}inline ll GetH1(int id,int x,int y){ return h1[id][y]-powG[y-x+1]*h1[id][x-1];}inline ll GetH2(int id,int x,int y){ return h2[id][x]-powG[y-x+1]*h2[id][y+1];}inline ll GetH(int i,int x,int y){ int lca=Getlca(x,y); ll s1=0,s2=0; ll tmp1=1,tmp2=powG[dep[x]-dep[lca]]; while(top[x]^top[lca]) { s1+=tmp1*GetH1(i,pos[top[x]],pos[x]); tmp1*=powG[dep[x]-dep[top[x]]+1]; x=fa[top[x]]; } if(x^lca)s1+=tmp1*GetH1(i,pos[lca]+1,pos[x]); while(top[y]^top[lca]) { s2=s2*powG[dep[y]-dep[top[y]]+1]+GetH2(i,pos[top[y]],pos[y]); y=fa[top[y]]; } if(y^lca)s2=s2*powG[dep[y]-dep[lca]]+GetH2(i,pos[lca]+1,pos[y]); return s1+tmp2*s2;}inline bool query(){ int m=read(),xx1=read(),yy1=read(),xx2=read(),yy2=read(); if(Getlen(xx1,yy1)!=Getlen(xx2,yy2))return false; static ll t1[27],t2[27]; static ll b[27]; static char ch[3]; for(int i=1;i<=26;i++) t1[i]=GetH(i,xx1,yy1),t2[i]=GetH(i,xx2,yy2); for(int i=1;i<=26;i++)anc[i]=i; while(m--) { scanf("%s",ch+1); int x=ch[1]-'a'+1,y=ch[2]-'a'+1; if(getf(x)!=getf(y))anc[anc[x]]=anc[y]; } for(int i=1;i<=26;i++) { if(getf(i)^i) { t1[getf(i)]+=t1[i],t2[getf(i)]+=t2[i]; } } ll cnt=0; for(int i=1;i<=26;i++) { if(getf(i)==i) { ll tmp=t1[i]-t2[i]; if(S.count(tmp)) { cnt++; b[i]=tmp; } else if(tmp==0)b[i]=0; else return false; } else b[i]=0; } if(!cnt)return true; if(cnt^2) return false; cnt=0; for(int i=1;i<=26;i++) { cnt+=b[i]; } return cnt==0;}int main(){ n=read(); powG[0]=1; for(int i=1;i<=n;i++) { powG[i]=powG[i-1]*G; if(!S.count(powG[i])) { S[powG[i]]=i; } if(!S.count(-powG[i])) { S[-powG[i]]=-i; } } S[1]=1;S[-1]=-1; for(int i=1;i<n;i++) { int x=read(),y=read(); char c;scanf("%c",&c); Insert(x,y,c-'a'+1); } SplitTree(); for(int i=1;i<=26;i++) { h1[i][0]=0; for(int j=1;j<=n;j++) { h1[i][j]=h1[i][j-1]*G+(val[idx[j]]==i?1:0); } h2[i][n+1]=0; for(int j=n;j>=1;j--) { h2[i][j]=h2[i][j+1]*G+(val[idx[j]]==i?1:0); } } int Q=read(); while(Q--) { if(query())puts("YES"); else puts("NO"); }}
0 0
- BJ模拟:相似子串(树链剖分+hash)
- BJ模拟(2) D3T2 相似子串
- BJ模拟:stwell(BFS)
- BJ模拟(2) D1T2 摩尔庄园
- BJ模拟(2) D2T2 随机游走
- BJ模拟(2) D2T3 路径规划
- BJ模拟(2) D3T1 and
- BJ模拟 医院(支配树DominatorTree)
- BJ模拟 等差数列(分块+FFT)
- BJ模拟 生日礼物(斯特林数+NTT)
- 相似子串 bzoj3230
- BZOJ3230 相似子串
- BJ模拟(1) D1T1 Delight for a Cat
- BJ模拟(1) D2T1 Bash Plays with Functions
- BJ模拟(1) D2T2 Alice and Bob IV
- BJ模拟(1) D2T3 链上求和
- BJ模拟(2) D2T1 简单粗暴的题目
- BJ模拟 Mortal Kombat(二分图匹配+tarjan)
- cesiumjs学习笔记之三——cesium-navigation插件
- No module named Tkinter
- 修改VirtualBox中mac的分辨率
- docker安装带GPU模式的caffe(Centos7)
- Lease timeout of 0 seconds expired. 租约过期
- BJ模拟:相似子串(树链剖分+hash)
- ubuntu 安装tar.gz包
- HDU1799 循环多少次?
- 微信分享 JSSDK的使用
- 三句代码创建全屏Dialog或者DialogFragment:带你从源码角度实现
- svn安装后,checkout到本地的文件夹不能正确显示图标(如绿色勾),解决过程
- UITableView使用总结和性能优化
- java基础----常用设计模式
- centos7 samb4