Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 如何找到所描述的给定条件的所有字符串?_String_Algorithm - Fatal编程技术网

String 如何找到所描述的给定条件的所有字符串?

String 如何找到所描述的给定条件的所有字符串?,string,algorithm,String,Algorithm,问题: 给定一个整数k 有一个字符串由1和0组成(例如“10110”), 在这里把它命名为二进制代码 二进制代码的长度为2^k+k-1(例如,给定的k为2,因此 二进制代码的长度为5) 如果二进制代码的长度k子字符串在二进制代码中只出现一次 那么二进制代码就是我们要寻找的。例如: 假设k为2(例如,匹配的二进制代码的长度为5 “10011”是一个匹配项,因为其长度2的子字符串是“10”、“00”、“01”、“11”,并且所有这些子字符串在二进制代码中只出现一次。)。所有这些二进制代码都是“001

问题:

  • 给定一个整数k
  • 有一个字符串10组成(例如“10110”), 在这里把它命名为二进制代码
  • 二进制代码的长度为2^k+k-1(例如,给定的k为2,因此 二进制代码的长度为5)
  • 如果二进制代码的长度k子字符串在二进制代码中只出现一次
  • 那么二进制代码就是我们要寻找的。例如:

    假设k为2(例如,匹配的二进制代码的长度为5 “10011”是一个匹配项,因为其长度2的子字符串是“10”、“00”、“01”、“11”,并且所有这些子字符串在二进制代码中只出现一次。)。所有这些二进制代码都是“00110”“10011”“11001”“01100”


    我正在寻找一种算法,以尽可能快地找到给定k的所有二进制代码。

    我尝试用以下方式解决此问题:

  • 找到所有可能的长度为k的子串并构建一个有向图 将这些字符串作为节点
  • 尝试查找有向图中的所有路径 它将只遍历所有节点一次。由…组成的字符串 路径中给定顺序的节点是与给定顺序匹配的字符串 条件
  • 下面是我用python编写的代码: 导入系统 导入类型

    def find_path(s_map, slen):
        res = set()
        if (s_map):
            for i in s_map:
                used = list()
                used.append(i)
                res = find_sub(s_map, used, res, slen)
    
        return len(res),res
    
    def find_sub(s_map, used, res, slen):
        if (set(used) != set(s_map)):
            for x in s_map[used[-1]]:
                if (x not in used):
                    used.append(x)
                    print used
    
                    if (set(used) == set(s_map)):
                        sub = used[:-1]
                        s = ''
                        for i in sub:
                            s += i[0]
                        s += used[-1]
                        print s, len(s), len(s_map)
                        if (len(s) == slen):
                            print s
                            res.add(s)
                    else:
                        find_sub(s_map, used, res, slen)
                    used.remove(x)
                else:
                    continue
    
        return res
    
    def build_map(s_list):
        s_map = dict()
    
        for s in s_list:
            l = (s_list[0:])
            l.remove(s)
            s_map[s] = [i for i in l if s[1:] == i[:-1]]
    
        return s_map        
    
    def binary_strings(k):
        if type(k) is types.IntType:
            return [(str(bin(i))[2:]).rjust(k, '0') for i in xrange(2 ** k) ]
    
    def main():
        print find_path(build_map(binary_strings(2)), 2**2+2-1)
        print find_path(build_map(binary_strings(3)), 2**3+3-1)
        print find_path(build_map(binary_strings(4)), 2**4+4-1)
    
    if __name__ == '__main__':
        sys(exit(main()))
    
    我们可以将二进制代码建模为长度
    k
    的所有组合的排列。我们有
    2^k
    组合,它们可以按
    (2^k)排列排列。这是相当多的代码,但满足要求3。长度
    2^k+k-1
    表示每个长度组合
    k
    的后缀必须是下一个组合的
    k-1
    前缀。当每个新组合添加一个新符号时,我们有第一个长度组合
    k
    2^k-1
    新的长度组合
    k
    。所以我们可以删减所有这些
    (2^k)相当快

    我们可以将长度
    k
    的组合建模为二进制数。然后,每个“代码”都可以从这些数字中的一个开始,下一个数字必须具有前一个数字的
    k-1
    位,并添加一个新的位0或1。它可以通过向左移动1并添加0或1,然后将掩码设置为
    k
    位来完成。新号码只能在尚未使用的情况下使用,因此我们必须记住使用的号码。我们将生成长度
    2^k
    的序列,以满足上述要求。结果,我们将这些序列转换成相应的二进制代码。这意味着我们使用第一个数字中的所有位,并从所有下一个数字中添加最小的位。或者我们可以从所有数字中使用最高位,并将最后一位的所有位相加

    在Erlang中生成的代码:

    -module(binary_code).
    
    -export([gen/1]).
    
    gen(K) ->
        N = (1 bsl K) - 1,
        gen(N, K, lists:seq(0, N)).
    
    gen(Mask, K, L) ->
        [ [ $0 + B || <<B:1>> <= <<X:K>> ] ++ V
         || X <- L, V <- gen(Mask, Mask, X, [X]) ].
    
    gen(_, 0, _, _) -> [[]];
    gen(Mask, N, Prev, Prefix) ->
        P = (Prev bsl 1) band Mask,
        [ [$0 + (X band 1)|V] || X <- [P, P bor 1],
                   not lists:member(X, Prefix),
                   V <- gen(Mask, N-1, X, [X|Prefix])
                  ].
    
    二进制代码的数量似乎是
    2^(2^(k-1))
    。它迅速升级。对于生成更高
    k
    的二进制代码,我建议使用C或ASM。(对于
    k=6
    ,2^32=4294967296)

    编辑

    有我的实现它在C和它的工作很好

    $ ./binary_code 1
    01
    10
    $ ./binary_code 2
    00110
    01100
    10011
    11001
    $ ./binary_code 3
    0001011100
    0001110100
    0010111000
    0011101000
    0100011101
    0101110001
    0111000101
    0111010001
    1000101110
    1000111010
    1010001110
    1011100010
    1100010111
    1101000111
    1110001011
    1110100011
    $ time ./binary_code 4 | wc
        256     256    5120
    
    real    0m0.003s
    user    0m0.000s
    sys     0m0.000s
    $ time ./binary_code 5 | wc
      65536   65536 2424832
    
    real    0m0.053s
    user    0m0.088s
    sys     0m0.000s
    $ ./binary_code 6 | head -n 20
    000000100001100010100011100100101100110100111101010111011011111100000
    000000100001100010100011100100101100110100111101101110101011111100000
    000000100001100010100011100100101100110100111111010101110110111100000
    000000100001100010100011100100101100110100111111011011101010111100000
    000000100001100010100011100100101100110101011101001111011011111100000
    000000100001100010100011100100101100110101011101001111110110111100000
    000000100001100010100011100100101100110101011101101111010011111100000
    000000100001100010100011100100101100110101011101101111110100111100000
    000000100001100010100011100100101100110101011110110111010011111100000
    000000100001100010100011100100101100110101011111101101110100111100000
    000000100001100010100011100100101100110110100111101010111011111100000
    000000100001100010100011100100101100110110100111101110101011111100000
    000000100001100010100011100100101100110110100111111010101110111100000
    000000100001100010100011100100101100110110100111111011101010111100000
    000000100001100010100011100100101100110110101011101001111011111100000
    000000100001100010100011100100101100110110101011101001111110111100000
    000000100001100010100011100100101100110110101011101111010011111100000
    000000100001100010100011100100101100110110101011101111110100111100000
    000000100001100010100011100100101100110110101011110111010011111100000
    000000100001100010100011100100101100110110101011111101110100111100000
    
    $ time ./binary_code 6 | wc
    4294967296 4294967296 300647710720
    
    real    123m18.854s
    user    183m36.848s
    sys     2m33.652s
    
    $ time ./binary_code 6 > /dev/null
    
    real    63m5.656s
    user    62m50.808s
    sys     0m11.072s
    

    它可以为
    k=6
    生成75MB/s的二进制代码。我也尝试过解决这个问题,但gcc必须在后台做一些惊人的事情,因为非递归版本比我的第一个直接递归版本慢10%左右。

    你的问题不清楚。你能重新表述你的问题陈述吗?在你的问题中也包括你的尝试,而不是作为答案。@AbhishekBansal我已经编辑了我的问题并试图弄清楚,有什么帮助吗?你如何知道每个
    k
    都有二进制代码?我的意思是符合所有要求(特别是4.)@Hynek Pichi Vychodil如果没有二进制代码与条件匹配,那么返回None就可以了。实际上我不知道每个
    k
    是否有二进制代码。谢谢。我可以从你的描述中得到你的想法。但是由于我不熟悉Erlang,请您用C/JAVA/Python/PHP来展示您的想法好吗?@Snowwolf:我添加了C代码。我认为它的速度可以通过更小的堆栈帧(我不喜欢全局变量)来提高,甚至可以避免递归,但这要困难得多。@Snowwolf我无法抗拒,所以我尝试了不使用递归的方法,但它不起作用。堆栈帧的大小似乎也没有任何影响。只有分支预测才重要。
    $ ./binary_code 1
    01
    10
    $ ./binary_code 2
    00110
    01100
    10011
    11001
    $ ./binary_code 3
    0001011100
    0001110100
    0010111000
    0011101000
    0100011101
    0101110001
    0111000101
    0111010001
    1000101110
    1000111010
    1010001110
    1011100010
    1100010111
    1101000111
    1110001011
    1110100011
    $ time ./binary_code 4 | wc
        256     256    5120
    
    real    0m0.003s
    user    0m0.000s
    sys     0m0.000s
    $ time ./binary_code 5 | wc
      65536   65536 2424832
    
    real    0m0.053s
    user    0m0.088s
    sys     0m0.000s
    $ ./binary_code 6 | head -n 20
    000000100001100010100011100100101100110100111101010111011011111100000
    000000100001100010100011100100101100110100111101101110101011111100000
    000000100001100010100011100100101100110100111111010101110110111100000
    000000100001100010100011100100101100110100111111011011101010111100000
    000000100001100010100011100100101100110101011101001111011011111100000
    000000100001100010100011100100101100110101011101001111110110111100000
    000000100001100010100011100100101100110101011101101111010011111100000
    000000100001100010100011100100101100110101011101101111110100111100000
    000000100001100010100011100100101100110101011110110111010011111100000
    000000100001100010100011100100101100110101011111101101110100111100000
    000000100001100010100011100100101100110110100111101010111011111100000
    000000100001100010100011100100101100110110100111101110101011111100000
    000000100001100010100011100100101100110110100111111010101110111100000
    000000100001100010100011100100101100110110100111111011101010111100000
    000000100001100010100011100100101100110110101011101001111011111100000
    000000100001100010100011100100101100110110101011101001111110111100000
    000000100001100010100011100100101100110110101011101111010011111100000
    000000100001100010100011100100101100110110101011101111110100111100000
    000000100001100010100011100100101100110110101011110111010011111100000
    000000100001100010100011100100101100110110101011111101110100111100000
    
    $ time ./binary_code 6 | wc
    4294967296 4294967296 300647710720
    
    real    123m18.854s
    user    183m36.848s
    sys     2m33.652s
    
    $ time ./binary_code 6 > /dev/null
    
    real    63m5.656s
    user    62m50.808s
    sys     0m11.072s