我正在处理二进制字符串(即它仅包含1和0),并且我需要运行N次函数。此函数将字符串中的“ 01”的任何实例替换为“ 10”。但是,str.replace需要花费太多时间来处理输出,特别是当字符串的长度以及N的长度可以达到10 ^ 6时。
我尝试实现正则表达式,但是它没有为我提供任何优化,而是花了更多时间来执行任务。
例如,如果提供给我的字符串为01011并且N等于1,则输出应为10101。类似地,如果N变为2,则输出为11010,依此类推。
在python中是否有对str.replace的优化,或者我可以做些什么操作来优化代码?
答案 0 :(得分:3)
让我们把输入想像成一个无符号整数,可能是一个很大的整数。例如:
1001 1011 # input number X
0100 1101 # Y = X>>1 = X//2 -- to get the previous bit to the same column
1001 0010 # Z1 = X & ~Y -- We are looking for 01, i.e. 1 after previous 0
0001 0010 # Z2 = Z1 with the highest bit cleared, because we don't want
# to process the implicit 0 before the number
1010 1101 # output = X + Z2, this adds 1 where 01's are;
# 1 + 01 = 10, this is what we want
因此,我们只需很少的算术运算就可以处理整个列表。
更新:示例代码,我试图解决有关前导零的注释。
xstr = input("Enter binary number: ")
x = int(xstr, base=2)
digits = len(xstr)
mask = 2**(digits-1) - 1
print("{:0{width}b}".format(x,width=digits))
while True:
z2 = x & ~(x >> 1) & mask
if z2 == 0:
print("final state")
break
x += z2
print("{:0{width}b}".format(x,width=digits))
答案 1 :(得分:2)
虽然这不是实际替换问题的答案,但我的初步调查表明,翻转规则最终会将所有1排在字符串的开头,将所有0排在结尾,因此以下函数将给出如果N接近len(s)
,则正确答案。
from collections import Counter
def asymptote(s, N):
counts = Counter(s)
return '1'*counts['1'] + '0'*counts['0']
我将结果与
def brute(s, N):
for i in range(N):
s = s.replace('01', '10')
return s
此图显示了在蛮力法和随机字符串的渐近结果之间有何一致之处
黄色部分是蛮力和渐近结果相同的地方。这样一来,您通常至少需要进行len(s)/2
次翻转才能获得渐近结果,有时甚至还需要更多一些(红线是3 * len(s)/ 4)。
答案 2 :(得分:0)
这是我谈到的程序:
from typing import Dict
from itertools import product
table_1 = {
"01": 1,
"11": 0,
}
tables = {
1: table_1
}
def _apply_table(s: str, n: int, table: Dict[str, int]) -> str:
tl = n * 2
out = ["0"] * len(s)
for i in range(len(s)):
if s[i] == '1':
if i < tl:
t = '1' * (tl - i - 1) + s[:i + 1]
else:
t = s[i - tl + 1:i + 1]
o = table[t]
out[i - o] = '1'
return ''.join(out)
def _get_table(n: int) -> Dict[str, int]:
if n not in tables:
tables[n] = _generate_table(n)
return tables[n]
def _generate_table(n: int) -> Dict[str, int]:
def apply(t: str):
return _apply_table(_apply_table(t, n - 1, _get_table(n - 1)), 1, table_1)
tl = n * 2
ts = (''.join(ps) + '1' for ps in product('01', repeat=tl - 1))
return {t: len(apply(t).rpartition('1')[2]) for t in ts}
def transform(s: str, n: int):
return _apply_table(s, n, _get_table(n))
这不是很快,但是transform
的时间复杂度为O(M)
,其中M是字符串的长度。但是_generate_table
函数的空间复杂度和不良的时间复杂度使其无法使用:-/(但是,您可以对其进行改进,或者以更快的速度在C中实现它。(它也会变得更好。如果您存储哈希表而不是每次都不重新计算)