树哈希
这种东西看代码比说话好用。
xor 多重集哈希
const ull mask=std::chrono::steady_clock::now().time_since_epoch().count();
int ull shift(ull x) {
x^=mask, x^=x<<13, x^=x>>7, x^=x<<17, x^=mask;
return x;
}
void dp(int x,int fa) {
int ms=0; siz[x]=1;
for(int y:to[x]) if(y^fa) dp(y,x), siz[x]+=siz[y], ms=max(ms,siz[y]);
ms=max(ms,n-siz[x]);
if(ms<=n/2) heart.pb(x);
}
void Hash(int x,int fa) {
hsh[x]=1;
for(int y:to[x]) if(y^fa) Hash(y,x), hsh[x]+=shift(hsh[y]);
trees.insert(hsh[x]);
}
heart.clear(), dp(1,0);
for(int rt:heart) {
trees.clear(), Hash(rt,0);
qwq=max(trees,qwq);
}
// jury hash is qwq.
质数表哈希
int vis[M], p[M], top;
void init() {
int d=1299709;
up(i,2,d) if(!vis[i]) {
vis[i]=1, p[++top]=i;
up(j,2,d/i) vis[i*j]=1;
}
}
struct Tree {
int n, siz[N]; ull hsh[N]; vector<int> to[N];
void build(int x) { n=x; }
void eadd(int u,int v) { to[u].pb(v), to[v].pb(u); }
void Hash(int x,int fa) {
hsh[x]=1, siz[x]=1;
for(int y:to[x]) if(y^fa) Hash(y,x), siz[x]+=siz[y], hsh[x]+=hsh[y]*p[siz[y]];
}
void change(int x,int fa,int I) {
if(fa) hsh[x]=hsh[x]+p[n-siz[x]]*(hsh[fa]-hsh[x]*p[siz[x]]);
for(int y:to[x]) if(y^fa) change(y,x,I);
}
};