生成具有所有唯一k位子序列的所有n位序列。

时间:2015-04-03 18:27:26

标签: algorithm bit

我发现了这个问题:

  

考虑36位的序列。每个这样的序列有32位5位   由相邻位组成的序列。例如,序列   1101011 ...包含5位序列11010,10101,01011,.......写一个   程序打印具有两个属性的所有36位序列:   1.序列的前5位是00000。   2.没有两个5位子序列是相同的。

因此我推广了所有具有k位唯一子序列的n位序列,以满足上述要求。然而,我能想到的唯一方法是使用残酷的力搜索:生成n比特序列的所有排列,其中前k个比特为零,然后对于每个序列,检查所有k比特子序列是否唯一。这显然不是一种非常有效的方法。我想知道有没有更好的方法来解决这个问题?

感谢。

2 个答案:

答案 0 :(得分:3)

最简单的方法似乎是一种回溯方法。您可以跟踪您使用平面阵列看到的5位序列。在每一位,尝试添加0 - counter = (counter & 0x0f) << 1并检查您之前是否已经看过,然后执行counter = counter | 1并尝试该路径。

可能有更高效的算法可以更快地修剪搜索空间。这似乎与https://en.wikipedia.org/wiki/De_Bruijn_sequence有关。我不确定,但我相信它实际上是等同的;也就是说,序列的最后五位必须是10000,使其成为循环。

编辑:这是一些c代码。由于递归,效率低于空间,但简单。最糟糕的是掩码管理。看来我对De Bruijn序列是正确的;这找到了所有2048个。

#include <stdio.h>
#include <stdlib.h>

char *binprint(int val) {
    static char res[33];
    int i;
    res[32] = 0;
    for (i = 0; i < 32; i++) {
        res[31 - i] = (val & 1) + '0';
        val = val >> 1;
    }
    return res;
}

void checkPoint(int mask, int counter) {
    // Get the appropriate bit in the mask
    int idxmask = 1 << (counter & 0x1f);

    // Abort if we've seen this suffix before
    if (mask & idxmask) {
        return;
    }

    // Update the mask
    mask = mask | idxmask;

    // We're done if we've hit all 32
    if (mask == 0xffffffff) {
        printf("%10u 0000%s\n", counter, binprint(counter));
        return;
    }

    checkPoint(mask, counter << 1);
    checkPoint(mask, (counter << 1) | 1);
}

void main(int argc, char *argv[]) {
    checkPoint(0, 0);
}

答案 1 :(得分:2)

我记得在我的编程面试问题书中看到了这个确切的问题。这是他们的解决方案:

Explanation of Algorithm 2

Algorithm 2 - Unique 5-bit Sequences

希望它有所帮助。欢呼声。