Статья Автор: Деникина Н.В., Деникин А.В.

Вопрос 24. Паттерны

ЕГЭ по информатике · паттерны

Задание 24

Семь методов обработки символьной строки, которые закрывают практически любую формулировку задания за 2020–2026 годы — с теорией и кодом на Python.

1 первичный баллрешения на Python8 задач на тренажёре7 паттернов
01

Однопроходный счётчик

«Максимальная цепочка символов по локальному правилу»

Признаки в условии

  • «максимальная» (реже минимальная) непрерывная цепочка
  • правило проверяется по соседним символам: все одинаковые, чередование, пары «гласная+согласная»

Идея

Один проход по строке. Держим cur — длину текущей цепочки и best — лучший результат. Пока правило выполняется, наращиваем cur; как только нарушено — сбрасываем в 1.

Шаблон решения

s = open('24.txt').read()
best = 1
cur = 1
for i in range(1, len(s)):
    if s[i] != s[i-1]:            # соседние различны
        cur += 1
        best = max(best, cur)
    else:
        cur = 1                   # новая цепочка с текущего символа
print(best)

Ловушки

  • Сброс cur = 0 вместо cur = 1 — текущий символ уже начало цепочки длины 1, иначе ответ на единицу меньше.
  • Для «пар / групп» удобен regex: re.findall(r'(?:[AEO][BCD])+', s), затем максимум по len // 2. Не забудь делить на 2, если спрашивают количество пар.
02

Запрет подстроки

«Максимальный фрагмент без заданной подстроки»

Признаки в условии

  • максимальная цепочка, которая не содержит подстроку (например XYZ)
  • либо запрещена смежность определённых символов

Идея

Запретную подстроку нельзя просто выбросить — её нужно разорвать, сохранив крайние символы. Вставляем пробел внутрь: XYZ → 'XY YZ', затем split по пробелу и максимум длины.

Способ 1 — замена с разрывом

s = open('24.txt').read()
parts = s.replace('XYZ', 'XY YZ').split(' ')
print(max(len(p) for p in parts))

Способ 2 — скользящее окно

s = open('24.txt').read()
P = 'XYZ'; m = len(P)
L = 0; best = 0
for R in range(len(s)):
    if R-m+1 >= L and s[R-m+1:R+1] == P:
        L = R - m + 2     # хвост P длиной m-1
    if R - L + 1 > best:
        best = R - L + 1
print(best)

Ловушки

  • Замена s.replace('XYZ',' ') (пробел вместо подстроки) — неверна: выбрасывает все три символа. На ABXYZCD верный ответ 4 (ABXY), а так получится 2.
  • Если подстрока длиннее трёх символов или с повторами — бери способ 2, он не зависит от перекрытий.

Способ 2 универсален. Не нужно думать как разбить строку правильно и ничего не упустить.
03

Предложения и слова

«Двухуровневый разбор текста: по точкам и по пробелам»

Признаки в условии

  • в файле буквы, пробелы и точки
  • ограничение на уровне предложения или на последовательность длин слов внутри него

Идея

Сначала делим текст на предложения по точкам, затем каждое предложение — на слова по пробелам. Дальше работаем с длинами слов.

Шаблон решения

text = open('24.txt').read()
sentences = text.split('.')           # грубое деление
best = 0
for sent in sentences:
    words = sent.split()              # слова предложения
    lengths = [len(w) for w in words]
    # строгое возрастание длин (для примера)
    if all(lengths[i] < lengths[i+1] for i in range(len(lengths)-1)):
        best = max(best, len(sent) + 1)   # +1 за точку
print(best)

Ловушки

  • Забыть про точку при подсчёте символов предложения и про пробел после точки.
  • Для «слова невозрастают» поменяй знак на lengths[i] >= lengths[i+1]; для «максимум слов» бери max(len(words)). Всегда проверяй на маленьком примере!
04

Структурные ограничения

«Обрамление, опорные символы, формат ответа»

Признаки в условии

  • фрагмент начинается и заканчивается одинаковыми символами или обрамлён цифрами
  • ответом служит само число или порядковый номер, а не длина

Идея

Запоминаем позиции «опорных» символов в массиве, затем перебираем подходящие пары границ. Внимательно читаем, что именно требуется в ответе.

Шаблон — макс. число с уникальными цифрами

import re
s = open('24.txt').read()
# (?<!\d) перед числом нет цифры, (?!\d) после числа нет цифры
# (?:[1-9]\d*|0) сразу отсекает ведущие нули
pat = r'(?<!\d)(?:[1-9]\d*|0)(?!\d)'
best = ''
for m in re.finditer(pat, s):
    num = m.group()
    if len(set(num)) == len(num):        # все цифры различны
        if len(num) > len(best) or (len(num) == len(best) and num > best):
            best = num
print(best)

опорыMN ровно k раз — через позиции

s = open('24.txt').read()
n = len(s); k = 100

# запоминаем позиции начала MN
pos = [i for i in range(n-1) 
         if s[i]=='M' and s[i+1]=='N']
m = len(pos); best = 0
for t in range(m - k + 1):
  left  = pos[t-1] + 1 if t >= 1 else 0
  right = pos[t+k] if t+k < m else n - 1
  if right - left + 1 > best:
    best = right - left + 1

print(best)

окноMN ровно k раз — два указателя

s = open('24.txt').read()
n = len(s); k = 100
L = 0; cnt = 0; best = 0
for R in range(n):
  if R >= 1 and s[R-1]=='M' and s[R]=='N':
      cnt += 1
  while cnt > k:
      if s[L]=='M' and s[L+1]=='N':
          cnt -= 1
      L += 1
  if cnt == k and R - L + 1 > best:
      best = R - L + 1
print(best)

Ловушки

  • Наивный \d+ поймает 007 как число, хотя ведущие нули не рассматриваются. Шаблон (?:[1-9]\d*|0) их отсекает.
  • Спутать формат ответа: вернуть длину, когда нужно само число или номер первого символа.
  • Опоры для MN: слева можно захватить хвостовой N предыдущего вхождения, справа — ведущий M следующего, поодиночке они нового MN не образуют.

Тренировка

Задача 1 — обрамление чётной цифрой

Последовательность максимальной длины из одинаковых букв, начинающаяся и заканчивающаяся одной и той же чётной цифрой, без других цифр и букв внутри.

Решить задачу
Показать подходСкрыть подход
Идём по строке, для каждой чётной цифры ищем ближайшую такую же справа, проверяя, что между ними только одинаковые буквы. Обрамляющие цифры учитываем в длине.
Задача 2 — макс. число с разными цифрами

Максимальное число, в десятичной записи которого все цифры различны. Число — максимальная последовательность цифр между нецифровыми символами.

Решить задачу
Показать подходСкрыть подход
Перебираем числа через regex (?<!\d)(?:[1-9]\d*|0)(?!\d), проверяем уникальность len(set(num))==len(num) и сравниваем как строки: длиннее = больше, при равной длине лексикографически (код выше).
05

Арифметические выражения

«Корректное выражение по regex + проверка значения»

Признаки в условии

  • в строке цифры, знаки + - * и мусор
  • нужно максимальное корректное выражение, иногда с условием на значение (равно 0, кратно числу)

Идея

Regex описывает корректное выражение: число — это 0 или [1-9]\d*, выражение — число с повторяющимися «знак + число». Найденное при необходимости вычисляем через eval.

Шпаргалка по regex

классынаборы символов

[ABC] — любой из A, B, C · [^ABC] — кроме них · [A-Z] — заглавная буква · [0-9] = \d

повторсколько раз

X+ — один и более · X* — ноль и более · X{3} — ровно 3 · X{2,4} — от 2 до 4

группаповтор блока

(?:AB)+ — блок AB один и более раз. (?:…) — незахватывающая группа, в задании 24 нужна почти всегда именно она.

числобез ведущих нулей

0|[1-9]\d* — либо одиночный 0, либо число с 1–9. Не пропускает 007.

Шаблон решения

import re
s = open('24.txt').read()
pat = r'(?:0|[1-9]\d*)(?:[+\-*](?:0|[1-9]\d*))*'
best = 0
for m in re.finditer(pat, s):
    expr = m.group()
    if len(expr) <= best:
        continue
    if eval(expr) == 0:           # условие задачи
        best = len(expr)
print(best)

Ловушки

  • Разрешить ведущие нули (\d+ вместо 0|[1-9]\d*).
  • Забыть приоритет умножения: 3*0+5 = 5, а не 0. Выражение равно нулю, когда каждое слагаемое (блок между +) содержит множитель 0.
  • Спецсимволы вне класса […] экранируй: \+, \*, \..

Тренировка

Задача 3 — буква A + выражение

Максимальная последовательность из буквы A, за которой следует корректное выражение без ведущих нулей.

Решить задачу
Показать подходСкрыть подход
Шаблон A(?:0|[1-9]\d*)(?:[+\-*](?:0|[1-9]\d*))*: буква A обязательна в начале, дальше — корректное выражение без ведущих нулей. Берём максимум по длине m.group().
06

Метод двух указателей

«Скользящее окно — доминирующий паттерн 2024–2026»

Признаки в условии

  • максимальная / минимальная подстрока
  • символ или подстрока встречается ровно / не менее / не более k раз

Идея

Две границы L и R задают окно. Правая граница расширяет окно; при нарушении инварианта левая граница сдвигается, сужая его. L движется только вправо — сложность линейная.

Базовый шаблон — не более 101 символа F

s = open('24.txt').read()
L = 0; cnt = 0; best = 0
for R in range(len(s)):
    if s[R] == 'F':
        cnt += 1
    while cnt > 101:            # нарушение — сдвигаем левую границу
        if s[L] == 'F':
            cnt -= 1
        L += 1
    if R - L + 1 > best:
        best = R - L + 1
print(best)

Четыре комбинации условий

максне более k

L=0; cnt=0; best=0
for R in range(len(s)):
    if s[R]=='F': cnt+=1
    while cnt > k:
        if s[L]=='F': cnt-=1
        L+=1
    if R-L+1 > best: best=R-L+1

минне менее k

L=0; cnt=0; best=10**9
for R in range(len(s)):
    if s[R]=='F': cnt+=1
    while cnt >= k:
        if R-L+1 < best: best=R-L+1
        if s[L]=='F': cnt-=1
        L+=1

максровно k

L=0; cnt=0; best=0
for R in range(len(s)):
    if s[R]=='F': cnt+=1
    while cnt > k:
        if s[L]=='F': cnt-=1
        L+=1
    if cnt==k and R-L+1 > best:
        best=R-L+1

минровно k

pos=[i for i in range(len(s))
     if s[i]=='F']
best=10**9
for t in range(len(pos)-k+1):
    d = pos[t+k-1]-pos[t]+1
    if d < best: best=d

Ловушки

  • Граница сдвига привязана к нарушению: «не более» — сужаем при cnt > k; «не менее» — окно валидно при cnt >= k, и минимум фиксируем внутри while. Для «ровно» добавь проверку cnt == k при записи ответа.
  • «Максимум при не менее k» почти не встречается отдельно — обычно «не менее» идёт в паре с поиском минимума.

Тренировка

Задача 4 — мин. длина с парой BD ≥ 200

Минимальное количество идущих подряд символов, среди которых пара BD встречается не менее 200 раз.

Решить задачу
Показать подходСкрыть подход
Шаблон «МИН, не менее k». Пара BD: при s[R]=='D' and s[R-1]=='B' увеличиваем счётчик; при сдвиге левой границы проверяем s[L]=='B' and s[L+1]=='D' и уменьшаем.
Задача 5 — 2026 ≥ 75 раз и ровно 90 X

Максимальная подстрока, где подстрока 2026 встречается не менее 75 раз и при этом содержится ровно 90 букв X.

Решить задачу
Показать подходСкрыть подход
Два счётчика в одном окне — формат демоверсии ЕГЭ-2026. Контролируем оба инварианта при сдвиге границ.
07

Полнота множества

«Окно, где присутствуют все нужные символы»

Признаки в условии

  • «присутствуют все цифры», «есть все буквы от A до N»
  • часто в комбинации с запретом или точным счётом других символов

Идея

Словарь хранит количество каждого нужного символа в окне. Переменная have — сколько разных нужных символов сейчас есть. Когда have равно размеру требуемого множества — окно валидно.

Шаблон — мин. окно со всеми цифрами, без A–F

s = open('24.txt').read()
need = set('0123456789')
forbid = set('ABCDEF')
cnt = {c: 0 for c in need}
have = 0; L = 0; best = 10**9
for R in range(len(s)):
    if s[R] in forbid:          # запрещённый символ — окно заново
        cnt = {c: 0 for c in need}
        have = 0; L = R + 1
        continue
    if s[R] in need:
        if cnt[s[R]] == 0:
            have += 1
        cnt[s[R]] += 1
    while have == len(need):    # все цифры есть — сужаем слева
        if R - L + 1 < best:
            best = R - L + 1
        if s[L] in need:
            cnt[s[L]] -= 1
            if cnt[s[L]] == 0:
                have -= 1
        L += 1
print(best)

Короткий вариант для минимума

s = open('24.txt').read()
last = {}                       # последняя позиция каждой цифры
best = 10**9
for R in range(len(s)):
    if s[R] in 'ABCDEF':
        last = {}               # сброс сегмента
        continue
    if s[R].isdigit():
        last[s[R]] = R
    if len(last) == 10:         # встречались все 10 цифр
        best = min(best, R - min(last.values()) + 1)
print(best)

Ловушки

  • При сдвиге левой границы уменьшай have только если убрали последний экземпляр символа.
  • Не путать «есть все нужные» (следим за have) и «ровно k штук» (следим за количеством) — иногда совмещены.
  • Короткий вариант хорош только для минимума; для максимума («все буквы A–N») нужен счётчик have и расширение окна.

Тренировка

Задача 6 — все буквы A–N, без цифр

Максимальное количество идущих подряд символов, среди которых есть все буквы от A до N и нет ни одной цифры.

Решить задачу
Показать подходСкрыть подход
Окно со словарём-счётчиком по буквам A–N, цифра сбрасывает окно. Версия на максимум: расширяем, фиксируем при have == 14.
Задача 7 — все цифры + ровно 3 буквы A–F

Минимальное количество идущих подряд символов, среди которых есть все цифры и ровно три буквы от A до F (других букв сколько угодно).

Решить задачу
Показать подходСкрыть подход
Два инварианта одновременно: have == 10 (все цифры) И cntAF == 3. Самая сложная задача блока — полнота множества плюс точный счёт.
Задача 8 — предложение со всеми буквами

Минимальная длина предложения, содержащего все латинские буквы.

Решить задачу
Показать подходСкрыть подход
Комбинация паттернов 03 + 07: split('.') → для каждого предложения проверка set(sent) >= set(alphabet) → минимум длины.
Семь паттернов покрывают все известные варианты задания 24 за 2020–2026 годы. Пиши код по шаблону паттерна, запускай на данных задачи и сверяй ответ на тренажёре SilverTests.
Печать