引言

上一篇文章中,我们生成了参数 m=3、n=4 时的所有可能 commafree code。本文将介绍如何从这18个码中挑选出一个最大的子集,使其满足 commafree code 的性质:当集合中任意两个码相连接时,不考虑首尾各n个字母后,中间所有长度为n的子串都不在这个集合中。

由于一个码可以和自身连接,比如选择0001后,序列00010001中的所有长度为4的中间子串(0010、0100、1000)都不能出现在最终集合中。这意味着如果我们选择了某个码,它的所有循环移位都不能再加入集合。因此,对每个主码,我们只需要从它的4个循环移位中选择一个加入集合。

Read more


引言

commafree code是一种编码方式,就像Huffman编码一样,在一个由m个字母构成的长度为n的单词集合D中,如果任意的两个单词之间的任意长度为n的字串不在D中出现,那么这个D最多可以由多少个不同的单词组成就是要研究的问题。但这里我们先把问题简化,考虑n=4的情况,比如likethis就符合条件,因为iket、keth、ethi就不是单词。另外,自身循环的也不考虑,比如dodo,如果是两个dodo拼接,那么dodo一定会出现在中间的子串中。

Read more


引言

我发现在以前的回溯算法中,很少提到链表的使用,虽然 Dancing link 算法已经用的炉火纯青了,但介绍它属于是“跳级”了,咱们既然从零单排回溯算法,那还要从链表在回溯中的简单用法讲起,这就要提 Langford 对的生成了。

Langford 对是一个组合数学中的概念。给定一个正整数 ,Langford 对是将数字 1 到 n 的每个数字重复两次,并以一种特定的方式排列,使得两个相同的数字之间恰好间隔等于该数字的位置数。 例如,对于 n=4,一种可能的 Langford 对排列是 23421314。在这里,每个数字重复两次,且两个 1 之间间隔 1 个位置;两个 2 之间间隔 2 个位置;以此类推。

Read more


引言

如果你看懂了上一篇的回溯基本法,那这篇更是小菜一碟,我将尝试在 read more 之前讲明白它。

相比基本法每次尝试是从$D_l$依次取一个然后验证,如果为假则剪枝,否则即等待成立,Walker 则从另一个角度出发,每次从$S_l$取完最小元素$x_l$后,直接更新下次的 $S_{l+1}$,把不符合条件从集合中删掉,然后接着往下走直到$l>n$。回溯时则直接令$S_l\leftarrow S_l \backslash x_l$ 去除$x_l$,然后接着选下一个。

Read more


引言

当我要介绍 Knuth 在 23 年圣诞节时的演讲 Dancing cell 时,我发现我缺少了太多的上下文,算法虽然不难讲清楚,但为什么要这么做,这个算法有什么应用价值我并不清楚,视频中提到了这是从 Knuth 的经典著作《The Art of Computer Programming》(TAOCP)第 7 章开始的。出于好奇,我翻看了整个第 7 章,发现整章都在讲述回溯算法(Backtrack),包括我之前提到的 Dancing Link 实际上是一个比较优化的算法。

Read more