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的所有二进制代码。我尝试用以下方式解决此问题:
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