Задача со сжатием строки RLE не проходит по памяти и по времени

Рейтинг: 1Ответов: 1Опубликовано: 30.05.2023

пишу код под задачу. Краткое описание задачи: Подается строка s в RLE виде. Назовём строку, из которой была получена s строкой t. Вам даны q запросов, каждый из них представлен целыми числами l и r. В каждом запросе вам необходимо найти длину сжатой подстроки t[l...r]. Выведите q чисел, каждое в отдельной строке — ответы на запросы в том порядке, в котором запросы были заданы во входных данных.

x1000000000yz

3

2 1000000001

2 1000000002

5938493 15938493

Ввод и Вывод

Собственно я ее решил, но памяти и по времени не проходит Вот мой код решения:

def encode(data):
    encoding = ''
    prev_char = ''
    count = 1

    for char in data:
        if char != prev_char:
            if prev_char and count == 1:
                encoding += prev_char
            elif prev_char:
                encoding += str(count) + prev_char
            count = 1    
            prev_char = char
        else:
            count += 1
    else:
        if count == 1:
            encoding += prev_char
        else:
            encoding += str(count) + prev_char
    return encoding 

   


def decode(data):
    decode = ''
    prev_char = ''
    count = ''
    for char in data:
        if char.isdigit():
            count += char
        elif char.isalpha() and count == '':
            decode += char
        else:
            decode += char * int(count)
            count = ''
    return decode



s = input()
numbers = [input().split() for _ in range(int(input()))]

n = decode(s)
for i in numbers:
    print(len(encode(n[int(i[0])-1:int(i[1])])))

Я еще новичок в программировании. Прошу помочь с оптимизацией, может посмотреть что-нибудь и переписать по-новому. Любую помощь.

Ответы

▲ 1

Похоже, вы строите всю исходную строку t

Вместо этого стоит построить набор отрезков, для каждого из которых указывается позиция начала и длина (или конец, если это будет удобнее), а также длину RLE для данного отрезка, а лучше накопленную длину RLE (от начала до текущего отрезка)

Для каждого запроса:

  • бинарным поиском (точное условие с ограничениями вы не привели, может хватить и линейного поиска) находите отрезок, содержащий начало, вычисляете, сколько этого отрезка захвачено, строите соотв. RLE
  • ищете отрезок, содержащий конец, вычисляете, сколько этого отрезка захвачено, строите соотв. RLE
  • добавляете длины RLE для всех промежуточных отрезков - это легко сделать, вычислив разность накопленных длин RLE

Сложность получается O(N+QlgN), где N - длина s, оно же пропорционально количеству отрезков, Q - количество запросов

Пример:

t=xxxyyyyyyyyyyyyyyyzzzzaa
s = 3x15y4z2a
             3x    15y   4z   2a
  char       x     y    z    a        //только для справки, в решении не нужен
  start      1     4    19   23       
  len        3     15   4    2        //на самом деле тоже можно не хранить, а смотреть разницу со следующим
  cumRLE     0     2    5    7   

Запрос 2,21 захватывает часть первого отрезка длиной 2, т.е. 2x - даёт вклад 2, часть третьего отрезка с длиной 3, 3z - тоже вклад 2, и от прмежуточных вклад 5-2=3, итого 7

Проверочка:

  |                  |              
 xxxyyyyyyyyyyyyyyyzzzzaa
  xxyyyyyyyyyyyyyyyzzz
  2x15y3z 
  длина 7