Loading

循环同构哈希

前置知识

单位根,哈希,分圆多项式

问题说明

定义循环向右位移一次为变换 \(W\),比如向量 \((2,3,4,7)\) 经过 \(W\) 变换会变成 \((7,2,3,4)\)

显然注意到 \(W^n(a)=a\),于是 \(W\) 构成了一个 \(n\) 元循环群。


定义两个向量 \(u,v\) 循环同构,当且仅当它们能通过若干次循环右移变相等。即存在 \(n\) 满足 \(W^n(u)=v\)

初始给定长度为 \(n\) 的向量 \(a_1=(1,0,0,\cdots ,0)\),进行 \(q\) 次操作,形如:

  • 1 x y:在向量序列 \(a\) 末尾插入向量 \(a_x+a_y\),其中加法定义为对应位相加。

  • 2 x:在向量序列 \(a\) 末尾插入向量 \(W(a)\)

  • 3 x y:询问向量 \(a_x,a_y\) 是否循环同构。

\(3\le n\le 10^4,q\le 10^6\)保证不卡哈希模数。

一些错误想法

暴力判断循环同构,复杂度 \(O(qn^2)\)

用最小表示法判断循环同构,复杂度 \(O(qn)\)


考虑 \(n\) 阶循环群,这东西同构于 \(n\) 阶单位根乘法群。

考虑 \(n\) 次单位根 \(w\),定义哈希函数:\(f(a)=\sum\limits_{i=0}^{n-1} a_iw^i\),则 \(f(W(a))=a_{n-1}+w\left(f(a)-a_{n-1}w^{n-1}\right)=wf(a)\)

\(\mathbb Z\) 下你就取 \(p=kn+1\) 形素数,然后取原根 \(g\),此时 \(w=g^k\) 就是 \(n\) 次单位根。


然后加法就直接加哈希值,循环位移就 \(\times w\),比较就判断 \(f(a_x)\times f(a_y)^{-1}\) 是否为 \(w^k\) 形式了。

直接预处理出 \(w^0,w^1,\cdots,w^{n-1}\),看看是否出现即可。

正解

上面那个单位根做法会有什么问题呢?

你注意到 \(\sum\limits_{i=0}^{n-1} w^i=0\),于是你无法区分形如 \((1,1,\cdots,1)\)\((2,2,\cdots,2)\) 这俩序列的哈希值。

此时你有一个很 trivial 的想法,就是你同时维护向量里所有数的和,然后也判断是否相等。

这样似乎就做完了?


我们观察刚才哈希错误的原因,是因为我们存在一个确定的(和你选的模数 \(p=kn+1\) 无关)整系数多项式 \(f\),使得 \(f(w)=0\)

由于分圆多项式的知识,次数最小的满足这个的多项式是分圆多项式 \(\Phi_n(x)\)

于是对于同时记录和的做法,我们构造 \(f(x)=\Phi_n(x)(x-1)\),此时若两个向量的差,和 \(f\) 的系数序列一致的话。

由于 \(f(w)=0,f(1)=0\),那么它们的哈希值相同,和也相同,但是它们不同。

你又坠机了。


此时我们类似思考:如果我们找到若干个点值 \(w_1,w_2,\cdots ,w_k\),使得次数最小的,满足 \(f(w_1),f(w_2),\cdots ,f(w_k)\) 均为 \(0\) 的多项式为 \(x^n-1\)

然后我们哈希 \(k\) 次,每次用 \(w_i\) 当哈希的 Base,然后模数不变依然是 \(p\)

那么由于 \(\deg(x^n-1)=n\),于是你构造不出 \(\deg f\le n-1\) 满足这个条件,此时两个哈希值冲突的概率就是正确的 \(\dfrac{1}{p}\) 了。


怎么找呢?由于分圆多项式的结论,你设 \(n\) 的所有因数为 \(d_1,d_2,\cdots ,d_k\),那么你取 \(w^{d_1},w^{d_2},\cdots ,w^{d_k}\) 就满足条件了。

因为 \(x^n-1=\prod\limits_{d\mid n}\Phi_d(x)\),然后你找所有因数对应的多项式自然就是所有的 \(\Phi_d(x)\) 了。


再次回顾一下算法流程:取 \(p=kn+1\) 形素数,然后取原根 \(g\),此时 \(w=g^k\) 就是 \(n\) 次单位根。

\(n\) 的所有因数为 \(d_1,d_2,\cdots ,d_k\)。下面都在 \(\bmod p\) 意义下:

令哈希函数 \(f_B(a)=\sum\limits_{i=0}^{D-1} a_iB^i\),对于 \(a\) 哈希成 \(\left(f_{(w^{d_1})}(a),\cdots,f_{(w^{d_k})}(a)\right)\) 这个 \(k\) 元组。

加法就直接点值加,循环位移就对应位依次乘 \(w^{d_1},w^{d_2},\cdots ,w^{d_k}\)

判断相等就依次取出两个第 \(i\) 位,判断是否对应点值除一下(模意义下)能被 \(w^{d_k}\) 的若干次幂表示出来。然后 \(w^{d_k}\) 的若干次幂显然可以预处理。

  • 复杂度 \(O(qd(n)\log p)\),其中 \(d(n)\) 是约数个数,最大为 \(64\)\(\log p\) 是因为求逆要快速幂。
posted @ 2025-06-16 11:59  HaHeHyt  阅读(170)  评论(0)    收藏  举报