提问人:niico 提问时间:11/11/2022 最后编辑:niico 更新时间:11/11/2022 访问量:48
如何修改大数的 de bruijn 算法?
How to modify de bruijn algorithm for large numbers?
问:
我有以下代码用于 de Bruijn 序列输出。 它适用于小数字,但如果 number = 18,则会抛出错误:
RecursionError: maximum recursion depth exceeded in comparison
我明白这与什么有关,如何在没有递归的情况下在这里编写 dfs 函数?
seen = set()
edges = []
def dfs(node, k, A):
for i in range(k):
str = node + A[i]
if (str not in seen):
seen.add(str)
dfs(str[1:], k, A)
edges.append(i)
def de_bruijn(n, k, A):
seen.clear()
edges.clear()
start_node = A[0] * (n - 1)
dfs(start_node, k, A)
s = ""
l = int(math.pow(k, n))
for i in range(l):
s += A[edges[i]]
s += start_node
return s
n = 18
k = 3
A = '012'
print(de_bruijn(n ,k, A))
答:
-1赞
btilly
11/11/2022
#1
超过递归限制不会让你做太多这样的事,因为问题会耗尽内存,但你必须把所有东西都变成一个显式的堆栈。这是您的代码:
def dfs(node, k, A):
for i in range(k):
str = node + A[i]
if (str not in seen):
seen.add(str)
dfs(str[1:], k, A)
edges.append(i)
现在的想法是,我们将有一个行动。它将具有类型和值。类型正在进入或退出函数和循环。每个操作都会执行一些代码。因此,新函数将具有以下结构:
def dfs (node, k, A):
stack = [('enter_function`, (node, k, A))]
while 0 < len(stack)
type, value = stack.pop()
if type == 'enter_function':
...
elif type == 'exit_function':
...
elif type == 'enter_loop':
...
elif type == 'exit_loop':
...
现在我们在每个部分做什么?这是显示这个想法的工作代码。请注意,我们放在堆栈上的第一件事是第二件事。因此,我们总是必须在进入之前先设置出口。
def dfs (node, k, A):
stack = [('enter_function', node)]
i = 0
while 0 < len(stack):
#print(stack)
action, value = stack.pop()
if action == 'enter_function':
node = value
for i in range(k-1, -1, -1):
stack.append(('enter_loop', i))
elif action == 'exit_function':
(node, i) = value
edges.append(i)
elif action == 'enter_loop':
i = value
string = node + A[i]
if string not in seen:
seen.add(string)
stack.append(('exit_function', (node, i)))
stack.append(('enter_function', string[1:]))
顺便说一句,性能提示。通过附加来构建一个大字符串需要时间。构建一个大型数组,然后加入它要快得多。O(n^2)
def de_bruijn(n, k, A):
seen.clear()
edges.clear()
start_node = A[0] * (n - 1)
dfs(start_node, k, A)
s = []
l = int(math.pow(k, n))
for i in range(l):
s.append(A[edges[i]])
s.append(start_node)
return "".join(s)
评论
0赞
niico
11/11/2022
我真的不明白我们为什么要添加堆栈?因此,如果实现了函数,我无法修复函数中出现的错误
0赞
btilly
11/11/2022
@niico我修复了代码。添加堆栈的原因是递归函数隐式维护堆栈。要摆脱它,您需要明确它。递归函数交错循环控制和函数调用。因此,显式堆栈还必须处理循环。
0赞
btilly
11/11/2022
同样在我的计算机上,摆脱递归让它运行. 很慢。我很确定你会在运行之前用完内存。n=12
n=13
n=18
0赞
btilly
11/11/2022
@niico 我还为您添加了一个性能提示。
评论