计算幺半群/半群的所有中缀积
Computing all infix products for a monoid / semigroup
简介:中缀产品组
假设我有一个群组
G = (G, *)
和元素列表
A = {0, 1, ..., n} ⊂ ℕ
x : A -> G
如果我们的目标是实现一个功能
f : A × A -> G
这样
f(i, j) = x(i) * x(i+1) * ... * x(j)
(我们不关心如果 i
> j
会发生什么)
然后我们可以通过预先计算 table 个前缀
来做到这一点
m(-1) = 1
m(i) = m(i-1) * x(i)
(右边的1
表示G
的单位)然后实现f
为
f(i, j) = m(i-1)⁻¹ * m(j)
之所以有效,是因为
m(i-1) = x(0) * x(1) * ... * x(i-1)
m(j) = x(0) * x(1) * ... * x(i-1) * x(i) * x(i+1) * ... * x(j)
等等
m(i)⁻¹ * m(j) = x(i) * x(i+1) * ... * x(j)
充分重新关联后。
我的问题
如果 G 只是一个幺半群,而不是群?
对于我的特定问题,如果 G = ([0, 1] ⊂ ℝ, *)
,我们可以做类似的事情吗,即我们有来自单位线的实数,我们不能除以 0 ?
是的,如果 G 是 ([0, 1] ⊂ ℝ, *),那么这个想法可以挽救,使得在 O(log n) 时间(或更准确地说,O( log z) 其中 z 是 A 中 a 的数量,其中 x(a) = 0).
对于每个 i,计算乘积 m(i) = x(0)*x(1)*...*x(i),忽略任何零(因此这些乘积将始终为非零) .此外,为所有零元素构建索引的排序数组 Z。
如果 [i, j] 范围内有零,则 i 到 j 的元素的乘积为 0,否则为 m(j) / m(i-1)。
要查找范围[i, j] 中是否有零,可以在Z 中二分查找Z 中>= i 的最小值,并将其与j 进行比较。这就是额外的 O(log n) 时间成本出现的地方。
一般幺半群解
在 G 是任意幺半群的情况下,可以对 n 个乘积进行预计算,使任意范围的乘积可在 O(log(j-i)) 时间内计算,尽管它比上面更具体的情况有点复杂.
不是预先计算前缀乘积,而是为所有 i、j 计算 m(i, j),其中 j-i+1 = 2^k 对于某些 k>=0,并且 2^k 同时除以 i 和 j。事实上,对于 k=0 我们不需要计算任何东西,因为 m(i, i+1) 的值只是 x(i).
所以我们需要计算n/2 + n/4 + n/8 + ...总产品,最多n-1个东西。
可以从这些构建块(和原始数组的元素)的 O(log_2(j-i+1)) 构造任意区间 [i, j]:选择最大的建筑物包含在区间中的块,并在它的两侧附加大小递减的块,直到到达 [i, j]。然后将每个构建块的预计算乘积 m(x, y) 相乘。
例如,假设您的数组大小为 10。例如,我假设幺半群是自然数的加法。
i: 0 1 2 3 4 5 6 7 8 9
x: 1 3 2 4 2 3 0 8 2 1
2: ---- ---- ---- ---- ----
4 6 5 8 3
4: ----------- ----------
10 13
8: ----------------------
23
此处,第 2、4 和 8 行显示长度为 2、4、8 的对齐间隔的总和(如果数组的长度不是 2 的幂,则忽略剩余的位)。
现在,假设我们要计算 x(1) + x(2) + x(3) + ... + x(8)。
即 x(1) + m(2, 3) + m(4, 7) + x(8) = 3 + 6 + 13 + 2 = 24。
简介:中缀产品组
假设我有一个群组
G = (G, *)
和元素列表
A = {0, 1, ..., n} ⊂ ℕ
x : A -> G
如果我们的目标是实现一个功能
f : A × A -> G
这样
f(i, j) = x(i) * x(i+1) * ... * x(j)
(我们不关心如果 i
> j
会发生什么)
然后我们可以通过预先计算 table 个前缀
来做到这一点m(-1) = 1
m(i) = m(i-1) * x(i)
(右边的1
表示G
的单位)然后实现f
为
f(i, j) = m(i-1)⁻¹ * m(j)
之所以有效,是因为
m(i-1) = x(0) * x(1) * ... * x(i-1)
m(j) = x(0) * x(1) * ... * x(i-1) * x(i) * x(i+1) * ... * x(j)
等等
m(i)⁻¹ * m(j) = x(i) * x(i+1) * ... * x(j)
充分重新关联后。
我的问题
如果 G 只是一个幺半群,而不是群?
对于我的特定问题,如果 G = ([0, 1] ⊂ ℝ, *)
,我们可以做类似的事情吗,即我们有来自单位线的实数,我们不能除以 0 ?
是的,如果 G 是 ([0, 1] ⊂ ℝ, *),那么这个想法可以挽救,使得在 O(log n) 时间(或更准确地说,O( log z) 其中 z 是 A 中 a 的数量,其中 x(a) = 0).
对于每个 i,计算乘积 m(i) = x(0)*x(1)*...*x(i),忽略任何零(因此这些乘积将始终为非零) .此外,为所有零元素构建索引的排序数组 Z。
如果 [i, j] 范围内有零,则 i 到 j 的元素的乘积为 0,否则为 m(j) / m(i-1)。
要查找范围[i, j] 中是否有零,可以在Z 中二分查找Z 中>= i 的最小值,并将其与j 进行比较。这就是额外的 O(log n) 时间成本出现的地方。
一般幺半群解
在 G 是任意幺半群的情况下,可以对 n 个乘积进行预计算,使任意范围的乘积可在 O(log(j-i)) 时间内计算,尽管它比上面更具体的情况有点复杂.
不是预先计算前缀乘积,而是为所有 i、j 计算 m(i, j),其中 j-i+1 = 2^k 对于某些 k>=0,并且 2^k 同时除以 i 和 j。事实上,对于 k=0 我们不需要计算任何东西,因为 m(i, i+1) 的值只是 x(i).
所以我们需要计算n/2 + n/4 + n/8 + ...总产品,最多n-1个东西。
可以从这些构建块(和原始数组的元素)的 O(log_2(j-i+1)) 构造任意区间 [i, j]:选择最大的建筑物包含在区间中的块,并在它的两侧附加大小递减的块,直到到达 [i, j]。然后将每个构建块的预计算乘积 m(x, y) 相乘。
例如,假设您的数组大小为 10。例如,我假设幺半群是自然数的加法。
i: 0 1 2 3 4 5 6 7 8 9
x: 1 3 2 4 2 3 0 8 2 1
2: ---- ---- ---- ---- ----
4 6 5 8 3
4: ----------- ----------
10 13
8: ----------------------
23
此处,第 2、4 和 8 行显示长度为 2、4、8 的对齐间隔的总和(如果数组的长度不是 2 的幂,则忽略剩余的位)。
现在,假设我们要计算 x(1) + x(2) + x(3) + ... + x(8)。
即 x(1) + m(2, 3) + m(4, 7) + x(8) = 3 + 6 + 13 + 2 = 24。