树hash
Posted segmenttree
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树hash相关的知识,希望对你有一定的参考价值。
神仙的博客(我就是用的这种方法)
树hash的方法很多,我用的是上面博客里面的方法
最近跟Wendigo神仙做题目,发现自己思维不行
题目
BJOI2015树的同构
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int mod=998244341;
const int N=100000;
const int M=1299720;
struct edge
{
int to,nxt;
}e[N*2];
int h[N],E=0;
ll f[N+5],g[N+5],siz[N];
int p[N+5],tot=0;
bitset<M+5> used;
vector<int> hs[N];
int n,m;
int vis[N];
void addedge(int u,int v)
{
E++;
e[E].to=v,e[E].nxt=h[u];
h[u]=E;
return;
}
void getsieve(int n)
{
used[0]=used[1]=1;
tot=0;
for(int i=2;i<=n;i++)
{
if(!used[i]) p[++tot]=i;
for(int j=1;j<=tot&&p[j]*i<=n;j++)
{
used[p[j]*i]=1;
if(i%p[j]==0) break;
}
}
return;
}
void dfs(int u,int fa)
{
f[u]=1;
siz[u]=1;
for(int i=h[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==fa) continue;
dfs(v,u);
siz[u]+=siz[v];
f[u]+=f[v]*p[siz[v]]%mod;
f[u]%=mod;
}
return;
}
void dfs1(int u,int fa)
{
g[u]=0;
if(u!=1)
{
g[u]=(f[fa]-p[siz[u]]*f[u]%mod+mod)%mod;
g[u]=(g[u]+g[fa]*p[n-siz[fa]]%mod)%mod;
}
for(int i=h[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==fa) continue;
dfs1(v,u);
}
return;
}
int cmp(vector<int> &a,vector<int> &b)
{
int la=a.size(),lb=b.size();
if(la!=lb) return 0;
for(int i=0;i<la;i++) if(a[i]!=b[i]) return 0;
return 1;
}
void insert(int tot)
{
scanf("%d",&n);
for(int i=1;i<=n;i++) h[i]=0;
E=0;
int fa;
for(int i=1;i<=n;i++)
{
scanf("%d",&fa);
if(!fa) continue;
addedge(i,fa);
addedge(fa,i);
}
dfs(1,0);
dfs1(1,0);
for(int i=1;i<=n;i++) hs[tot].push_back((g[i]*p[n-siz[i]]%mod+f[i])%mod);
sort(hs[tot].begin(),hs[tot].end());
return;
}
int main()
{
getsieve(M);
scanf("%d",&m);
for(int i=1;i<=m;i++) insert(i);
for(int i=1;i<=m;i++) vis[i]=i;
for(int i=1;i<=m;i++)
{
for(int j=i+1;j<=m;j++)
{
if(cmp(hs[i],hs[j]))
{
vis[j]=min(vis[j],i);
}
}
}
for(int i=1;i<=m;i++) printf("%d
",vis[i]);
return 0;
}
[JSOI2016]独特的树叶
枚举那个树叶,然后在父亲的hash值减2,然后在map里面找
附一张图
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int mod=999999137;
const int N=100000;
const int M=1299720;
struct edge
{
int to,nxt;
}e[N*2+5];
int h[N+5],E=0;
ll f[N+5],g[N+5],t[N+5],siz[N+5];
int p[N+5],tot=0;
bitset<M+5> used;
map<int,int> c;
int n,deg[N+5],pa[N+5];
int root=0;
void addedge(int u,int v)
{
E++;
e[E].to=v,e[E].nxt=h[u];
h[u]=E;
return;
}
void getsieve(int n)
{
used[0]=used[1]=1;
tot=0;
for(int i=2;i<=n;i++)
{
if(!used[i]) p[++tot]=i;
for(int j=1;j<=tot&&p[j]*i<=n;j++)
{
used[p[j]*i]=1;
if(i%p[j]==0) break;
}
}
return;
}
void dfs(int u,int fa)
{
f[u]=1;
siz[u]=1;
pa[u]=fa;
for(int i=h[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==fa) continue;
dfs(v,u);
siz[u]+=siz[v];
f[u]+=f[v]*p[siz[v]]%mod;
f[u]%=mod;
}
return;
}
void dfs1(int u,int fa)
{
g[u]=0;
if(u!=root)
{
g[u]=(f[fa]-p[siz[u]]*f[u]%mod+mod)%mod;
g[u]=(g[u]+g[fa]*p[n-siz[fa]]%mod)%mod;
}
for(int i=h[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==fa) continue;
dfs1(v,u);
}
return;
}
int main()
{
getsieve(M);
scanf("%d",&n);
int u,v;
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
root=1;
dfs(root,0);
dfs1(root,0);
for(int i=1;i<=n;i++)
{
c[(f[i]+g[i]*p[n-siz[i]]%mod)%mod]++;
}
n++;
for(int i=1;i<=n;i++) h[i]=0;
E=0;
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
deg[u]++,deg[v]++;
addedge(u,v);
addedge(v,u);
}
for(int i=1;i<=n;i++) if(deg[i]>1) root=i;
dfs(root,0);
dfs1(root,0);
for(int i=1;i<=n;i++) t[i]=(f[i]+g[i]*p[n-siz[i]]%mod)%mod;
for(int i=1;i<=n;i++)
{
if(deg[i]>1) continue;
ll has=(t[pa[i]]-2+mod)%mod;
if(c[has]) return printf("%d
",i),0;
}
return 0;
}
以上是关于树hash的主要内容,如果未能解决你的问题,请参考以下文章