通过过去的耦合抽样随机子树,如承诺所述。
import collections
import itertools
import random
test_tree = [None, 0, 0, 2, 3, 3]
class AddNode:
def __init__(self, u):
self._u = u
def __call__(self, tree, nodes):
if tree[self._u] in nodes:
nodes.add(self._u)
class DiscardNode:
def __init__(self, u):
self._u = u
def __call__(self, tree, nodes):
if all(tree[v] != self._u for v in nodes):
nodes.discard(self._u)
def sample_subtree(tree):
n = len(tree)
T = 1
steps = []
while True:
for t in range(T):
steps.append(random.choice([AddNode, DiscardNode])(random.randrange(1, n)))
upper = set(range(n))
lower = {0}
for step in reversed(steps):
step(tree, upper)
step(tree, lower)
if upper == lower:
return upper
T *= 2
def is_subtree(tree, nodes):
return all(node == 0 or tree[node] in nodes for node in nodes)
def test():
n = len(test_tree)
counter = collections.Counter()
for i in range(100000):
counter[frozenset(sample_subtree(test_tree))] += 1
print(min(counter.values()) / max(counter.values()))
assert all(is_subtree(test_tree, sub) for sub in counter)
for k in range(1, n + 1):
for comb in itertools.combinations(range(1, n), k):
nodes = frozenset((0,) + comb)
assert not is_subtree(test_tree, nodes) or nodes in counter
test()
O(m N)
个条目的数据结构,其中m
是大树的大小,而N
是您想要的树的大小。每个条目都将是一个计算子树的大整数。这将占用大量内存。不过,您可以只存储每个数字的log
。生成树的时间复杂度大约为O(N^2 b)
,其中b
是分支因子。这样做可以接受吗? - btilly