Подготовка к школе
1 класс
2 класс
3 класс
4 класс
5 класс
6 класс
7 класс
8 класс
9 класс
10 класс
11 класс
ОГЭ
ЕГЭ
Для всех
Назад

24. Подсчет символов: #297632

Сообщить о проблеме
Задание #297632
Задание было решено верно
Задание было решено неверно

Текстовый файл состоит из цифр $0$, $1$, $2$, $3$, $4$ и знаков арифметических операций «$-$» и «$+$» (вычитание и сложение). Определите максимальное количество символов в непрерывной последовательности, которая является корректным арифметическим выражением с целыми неотрицательными числами. В этом выражении никакие два знака арифметических операций не стоят рядом, в записи чисел отсутствуют незначащие (ведущие) нули и число $0$ не имеет знака.

В ответе укажите количество символов.

Знаки операций здесь другие — вместо умножения сложение, — но на алгоритм это не влияет никак. Важно лишь то, что оба символа являются разделителями между числами, а сами по себе выражением не являются.

Отдельно отмечу оговорку «число $0$ не имеет знака». Она означает, что запись вида $+0$ или $-0$ как отдельного числа не рассматривается: знак у нас всегда бинарная операция между двумя числами, а не унарный минус или плюс. Поэтому корректное выражение обязано начинаться и заканчиваться цифрой.

Корректное выражение — это число, за которым идёт любое количество пар «знак операции плюс число». Число — либо одиночный $0$, либо цифра из $1$–$4$, за которой идут любые цифры набора $0$, $1$, $2$, $3$, $4$. Запрет ведущих нулей означает ровно одно: с нуля может начинаться только само число $0$.

Помним про подстроку: фрагмент имеет право начаться в середине блока цифр, отбросив ведущие нули. Но у обрезанного старта есть плата — продолжить его влево знаком операции нельзя, слева стоит цифра. Присоединять что-то слева можно только когда число начинается с самого начала своего блока цифр. Это и отражает переменная chain.

Идём слева направо и для каждой позиции $j$ с цифрой считаем $L[j]$ — длину самого длинного корректного выражения, кончающегося в этой позиции. Вариантов два: либо это одно число, либо к числу слева через знак операции приклеивается уже посчитанное выражение, кончавшееся на два символа левее начала числа.

s = open('24-26-1.txt').read().strip()
n = len(s)
ops = set('-+')

L = [0] * n          # L[j] — длина макс. верного выражения, кончающегося в j
best = 0
r = 0                # начало текущего блока цифр

for j in range(n):
    if s[j] in ops:
        r = j + 1
        continue

    # 1) выражение из одного числа
    if s[r] != '0':                     # блок начинается со значащей цифры
        cur = j - r + 1
        chain = r
    elif j == r:                        # само число 0
        cur = 1
        chain = r
    else:                               # блок начался с 0 — стартуем с первой ненулевой
        q = r
        while q <= j and s[q] == '0':
            q += 1
        cur = j - q + 1 if q <= j else 1
        chain = -1                      # слева цифра, знак операции не приписать

    # 2) приклеиваем слева выражение через знак операции
    if chain >= 2 and s[chain-1] in ops and L[chain-2] > 0:
        cur = max(cur, L[chain-2] + 1 + (j - chain + 1))

    L[j] = cur
    best = max(best, cur)

print(best)   # 144

Проверка найденного фрагмента: длина $144$, он целиком распознаётся регулярным выражением для корректной записи. Слева от него идёт $1+-$, то есть перед стартом знак, а перед ним ещё один — влево не растянуть. Справа фрагмент кончается на $2-12$, а дальше $-++$, снова два знака подряд.

Показать
Очки опыта 20
Спросить Зави
0 заданий сегодня

Предложить улучшение