De Bruijn序列的生成及其应用

上次美团的面试题:

   首先回顾一下题意:


分析可知 :
(1)长度为 n的 01 串集合 S共有 个元素 ;
(2)
在一个长度为m的01串中找出所有长度为m的循环子串,最多有m个(不重复的情况下),那么我们要求的B串长度最短也要2n,而且B串的每个长度为n的子串都不重复。

我们想一下,对于B串任意两个相邻的子串(长度为n),前一个子串舍去首字母,在尾部追加0或者1,变成另一个子串;如果我们把这种变化看成一条有向边,每个长度为n的子串看成一个节点,显然,每个节点出度均为2,入度也为2(因为每个节点都仅由两个节点变来)。如下图:(N=2)

De Bruijn序列的生成及其应用_第1张图片

如果我们能够找到一条经过每个节点一次且仅一次的回路,这个问题也就是经典的Hamilton回路问题,而这条路径就是要找的B串。如上图,我们找到一条Hamilton回路:00->01->11->10 ->00,对应的路径为:1100.

经过上面的分析,找到一种解决问题的方法:建图+找Hamilton回路。而寻找Hamilton回路是个NP完全问题,但由于这个问题的特殊性,每个点的出度均为2,搜索时间复杂度为O(2n)。

还有一个细节,图中的每个节点如何表示?

前面的分析可知,将每个子串对应成二进制,正好与区间[0,2^n)内每一个整数一一对应,于是我们直接用[0,2^n)的整数表示节点编号,通过位运算到达相邻的节点。

问题分析到这里似乎将要告一段落,但是仔细分析上面的图,看边上的数字,好像正好构成n=3的所有01串的集合,我们找到一个经过所有边的一次仅且一次的环,环路上的红色数字就是n=3时的B串。而这个问题正是经典的Euler回路问题。

图中每个节点的出度和入度均为2,这个图一定存在Euler回路。接下来直接找一条Euler回路就可以解决这个问题了。

 

综上所述,解决这个问题的时间复杂度O(2n),空间复杂度O(2n)



你可能感兴趣的:(剑指offer)