【模板】树hash
方法1.
const int seed = 12289;
ull hsh[N], rec[N];//hsh[i] 表示以 i 为根节点的子树的hash值
int sz[N];
vector<int>vec[N];
void chash(int u,int fa){
sz[u] = 1;
for(int v:vec[u]){
if(v==fa)
continue;
chash(v, u);
sz[u] += sz[v];
}
int cnt = 0;
for(int v:vec[u]){
if(v==fa)
continue;
rec[++cnt] = hsh[v];
}
sort(rec + 1, rec + 1 + cnt);
ull val = 0;
for (int i = 1;i<=cnt;i++){
val = val * seed + rec[i];
}
hsh[u] = val ? val * sz[u] : 1;
}
可以被下图hack
方法2.
const int seed = 12289;
ull hsh[N], rec[N];//hsh[i] 表示以 i 为根节点的子树的hash值
int sz[N];
vector<int>vec[N];
ull chash(int u, int fa)
{
sz[u] = 1, hsh[u] = 1;
for (int v : vec[u]) {
if (v == fa)
continue;
hsh[u] ^= chash(v, u) * seed + sz[v];
sz[u] += sz[v];
}
return hsh[u];
}
由于异或的性质,如果一个节点下有多棵本质相同的子树,这种哈希值将无法分辨该种子树出现 1,3,5.... 次的情况。