【模板】树hash

转载自OI Wiki 树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.... 次的情况。

原文地址:https://www.cnblogs.com/valk3/p/13500654.html