如何压缩字母序列?

时间:2018-01-12 20:20:30

标签: python-3.x

我想将序列“AABBAABBAC”压缩为“(A2B2)2AC”。

我的Python代码已打印“A2B2A2B2C”,但我无法设法执行“(A2B2)2”分组部分。

这是我的代码:

def compact_rep(seq):
    comp=[]
    i=0
    cont=1
    for i in range(0,len(seq)-1):
        if seq[i] == seq[i+1]: 
            cont+=1 
        else:
            comp.append(seq[i]) 
            if cont>1:
                comp.append(cont)
            cont=1
    if cont>1:
        comp.append(seq[i]) 
        comp.append(cont) 

    else:
        comp.append(seq[i+1])
    return ''.join([str(x) for x in comp])

如何让它也可以进行第二次分组?

1 个答案:

答案 0 :(得分:0)

对于有效的算法,您应该查看后缀树/数组。

但是如果你需要相对较短的字符串,那么你可以使用带有后引用的正则表达式,从而产生相对简单的代码:

  • 首先查找最长的重复次数,使用贪婪的匹配最大化重复次数
  • 使用回调函数进行替换
  • 重复上述内容,只要有匹配
  • 确保从匹配项中排除数字和括号

这可能会产生类似于"((AB)2)2"的嵌套结果,可以进一步简化(到#34;(AB)4")。在上述每次成功更换后,应对此进行验证和更换。

代码:

import re

def compact_rep(seq):
    def repl(m):
        opening = m.group(1)
        first = m.group(2)
        repetitions = m.group(3)
        closing = m.group(4)
        wrapper_repeat = m.group(5)
        repeats = 1 + len(repetitions) // len(first)
        if len(first) > 1:
            first = '(' + first + ')'
        if opening and wrapper_repeat:
            # simplify
            repeats = repeats * int(wrapper_repeat)
            return first + str(repeats)
        return opening + first + str(repeats) + closing + wrapper_repeat

    seq2 = '';
    while seq2 != seq:
        seq2 = seq
        seq = re.sub(r'(\(?)([^\d()]+)(\2+)(\)?)(\d*)', repl, seq2)
    return seq

res = compact_rep('BBBACACBDBDACACBDBDACACBDBDACACBDBDAC')
print(res) # B3((AC)2(BD)2)4AC