首页 > 其他分享 >树哈希

树哈希

时间:2023-11-05 21:23:51浏览次数:34  
标签:prime int hsh Dfs si 哈希

树哈希

  • 用于解决树同构问题

    • 树同构

      对于两个树 \(T_1\) 和 \(T_2\),如果能够把树 \(T_1\) 的所有点重新标号,使得树 \(T_1\) 和树 \(T_2\) 完全相同,那么这两个树是同构的。也就是说,它们具有相同的形态

  • 方法

    • 将子树大小等信息进行哈希

    • 用 unsigned long long 自然溢出

  • 法一:$ Xor $ _ $ shift $

    • 貌似不太好进行换根
# define i64 long long

unsigned i64 Xor_shift(unsigned i64 x){
    x ^= x >> 13;
    x ^= x << 7;
    x ^= x >> 17;
    return x;
}

void Dfs(int x){
    hsh[x] = 1;
    for(auto i : e[x]){
        Dfs(i);
        hsh[x] += Xor_shift(hsh[i]);
    }
}

  • 法二:对 $ size $ 哈希

    • 用质数表作为哈希函数

    • 换根大法好,用于无根树树哈希

    • 也可以以重心为根进行树哈希,只需要做1或2次

void Dfs(int x){
	si[x] = 1;
    hsh[x] = 1;
	for(auto i : e[x]){
		Dfs(i);
		si[x] += si[i];
		hsh[x] += hsh[i] * prime[si[i] - 1];
	}
}

//换根
void Dfs2(int x){
	for(auto i : e[x]){
		f[i] = (f[x] - hsh[i] *  prime[si[i] - 1]) * prime[n - si[i] - 1] + hsh[i];
		Dfs2(i);
	}
}

P5043 【模板】树同构([BJOI2015]树的同构)

# include <bits/stdc++.h>
# define int long long
using namespace std;
const int MOD = 998244353;
const int N = 1000 + 10;

int m;
int n, fa, si[N];
unsigned int hsh[N], f[N];
vector <int> e[N];
vector <unsigned int> temp;
map <vector <unsigned int>, int> rec;

bool p[N];
vector <int> prime;
void Euler(){
	int k = 1000;
	for(int i = 2; i <= k; i++){
		if(p[i] == 0){
			prime.push_back(i);
		}
		for(auto j : prime){
			if(i * j > k){
				break;
			}
			p[i * j] = 0;
			if(i % j == 0){
				break;
			}
		}
	}
}

void Dfs(int x){
	si[x] = 1;
	for(auto i : e[x]){
		Dfs(i);
		si[x] += si[i];
		hsh[x] += hsh[i] * prime[si[i] - 1];
	}
}

void Dfs2(int x){
	for(auto i : e[x]){
		f[i] = (f[x] - hsh[i] *  prime[si[i] - 1]) * prime[n - si[i] - 1] + hsh[i];
		Dfs2(i);
	}
}

signed main(){
//	freopen("1.in", "r", stdin);
	Euler();
	cin >> m;
	for(int i = 1; i <= m; i++){
		int rt = 0;
		cin >> n;
		for(int j = 1; j <= n; j++){
			hsh[j] = 1, f[j] = 0, si[j] = 0;
			e[j].clear();
		}
		for(int j = 1; j <= n; j++){
			cin >> fa;
			if(fa == 0){
				rt = j;
			}else{
				e[fa].push_back(j);
			}
		}
		Dfs(rt);
		f[rt] = hsh[rt];
		Dfs2(rt);
		
		temp.clear();
		sort(f + 1, f + 1 + n);
		for(int j = 1; j <= n; j++){
			temp.push_back(f[j]);
		}
		if(rec[temp] == 0){
			rec[temp] = i;
		}
		cout << rec[temp] << "\n";
	}
}

标签:prime,int,hsh,Dfs,si,哈希
From: https://www.cnblogs.com/wangyangjena/p/17811204.html

相关文章

  • java基础:再哈希法解决哈希冲突代码示例
    再哈希法(Rehashing)是解决哈希冲突的另一种方法。它与开放定址法不同,再哈希法使用多个哈希函数来确定冲突元素的位置,而不是在同一个哈希表中进行探测。下面是一个使用再哈希法解决哈希冲突的示例代码:publicclassRehashingHashTable{privateEntry[]table;privateint......
  • 字符串哈希
    算法原理:将一个字符串看成是一个P进制的数字。代码模板:def__init__(self,s):n=len(s)self.BASE=BASE=131#进制131,131313self.MOD=MOD=10**13+7#10**9+7,998244353,10**13+7self.h=h=[0]*(n+1)......
  • AI问答:关于字符串匹配算法的区别及应用场景,哈希/kmp/字典树/AC自动机
    1. 哈希(Hashing):哈希是一种将字符串转换为唯一标识符的技术,通常用于字符串的快速查找和比较。实现难度相对较低,但需要处理哈希冲突的问题。哈希在处理大量数据的查找和比较问题时非常实用。2. KMP(Knuth-Morris-Pratt):KMP 是一种用于字符串匹配的算法,特别适用于查找子串在主串中的......
  • 如何更新哈希映射中给定键的值?
    内容来自DOChttps://q.houxu6.top/?s=如何更新哈希映射中给定键的值?假设我们在Java中有一个HashMap<String,Integer>。如何更新(递增)我找到的每个字符串键的整数值?人们可以删除并重新输入键值对,但担心会有性能问题。另一种方法是只插入新的键值对,旧的将被替换。在后一种......
  • c++实现哈希桶
    闭散列的回顾在前面的学习中我们知道了闭散列的运算规则,当两个数据计算得到的位置发生冲突时,它会自动的往后寻找没有发生冲突的位置,比如说当前数据的内容如下:当插入的数据为33时计算的位置为3,可是位置3已经被占领了并且4也被占领了,但是位置5没有被占领所以插入数据33就会占领位置5,......
  • 数据结构与算法 | 哈希表(Hash Table)
    哈希表(HashTable)在二分搜索中提到了在有序集合中查询某个特定元素的时候,通过折半的方式进行搜索是一种很高效的算法。那能否根据特征直接定位元素,而非折半去查找?哈希表(HashTable),也称为散列表,就是一种数据结构,用于实现键-值对的映射关系。它通过将键映射到特定的值(哈希值)来实现......
  • 力扣2610. 转换二维数组(哈希表)
    给你一个整数数组 nums 。请你创建一个满足以下条件的二维数组:二维数组应该 只 包含数组 nums 中的元素。二维数组中的每一行都包含 不同 的整数。二维数组的行数应尽可能 少 。返回结果数组。如果存在多种答案,则返回其中任何一种。请注意,二维数组的每一行上可以......
  • 选修课-字符串哈希表排序
    题目:现有两门选修课,每门选修课都有一部分学生选修,每个学生都有选修课的成绩,需要你找出同时选修了两门选修课的学生,先按照班级进行划分,班级编号小的先输出,每个班级按照两门选修课成绩和的降序排序,成绩相同时按照学生的学号升序排序。学号+成绩组成,中间,分割;要求:1.选出同时选修两门......
  • 刷题笔记——哈希表(C)
    215.数组中的第K个最大元素-力扣(LeetCode)给定整数数组nums和整数k,请返回数组中第**k**个最大的元素。请注意,你需要找的是数组排序后的第k个最大的元素,而不是第k个不同的元素。你必须设计并实现时间复杂度为O(n)的算法解决此问题。解题思路哈希+开放定址法注......
  • leetcode(力扣) 128. 最长连续序列(哈希)
    文章目录题目描述思路分析完整代码题目描述给定一个未排序的整数数组nums,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。请你设计并实现时间复杂度为O(n)的算法解决此问题。示例1:输入:nums=[100,4,200,1,3,2]输出:4解释:最长数字连续序列是[1,2,3,4]。......