Подготовка к ЕГЭ: Решение 24-й задачи разными методами
Ключевые тезисы:
- Урок посвящен решению 24-й задачи ЕГЭ по информатике (обработка символьных строк).
- Основной упор делается на метод двух указателей как наиболее универсальный и эффективный.
- Рассматриваются альтернативные подходы: двойные циклы, регулярные выражения и другие эвристики.
- Ключевой момент — проверка условий внутри подстроки (буквы, цифры, символы).
- Цель — научиться выбирать подходящий метод, правильно определять условия для "сброса" и уверенно решать задачи на экзамене.
Основные подходы к решению
Метод двух указателей (Sliding Window)
- Основная идея: Использование двух индексов (левый
Lи правыйR), которые движутся по строке, динамически отслеживая выполнение условий задачи. Указатели определяют текущий отрезок и двигаются только при соблюдении условий. - Преимущества:
Высокая эффективность (линейная сложность).
Универсальность — подходит для большинства задач.
Позволяет обрабатывать строку за один проход.
- Схема работы:
- Правый указатель (
R) движется вперёд, накапливая нужные величины (например, счётчики символов). - Если какое-то условие нарушается (например, превышен лимит), левый указатель (
L) "подтягивается", уменьшая счётчики. - В подходящие моменты проверяется основное условие задачи и обновляется ответ.
- Правый указатель (
Двойные циклы (вложенные, Brute Force)
- Основная идея: Перебор всех возможных подстрок с помощью внешнего (
i) и внутреннего (j) циклов. - Когда использовать: Когда условия сложные и требуют проверки всех возможных подстрок, или когда метод двух указателей сложно адаптировать.
- Преимущества:
Простота реализации и понимания.
- Недостатки:
Низкая производительность (квадратичная сложность).
Может не уложиться в ограничения по времени на больших данных.
Регулярные выражения
- Основная идея: Использование шаблонов для поиска подстрок, удовлетворяющих сложным условиям.
- Применение: Хорошо подходит для задач с чёткими шаблонами (например, арифметические выражения).
- Ограничение: Может быть неудобно для задач с пересекающимися или вложенными паттернами.
Разбор ключевых задач
Задача 1: Поиск максимальной подстроки (двойной цикл vs два указателя)
Условие: Найти максимальную подстроку, оканчивающуюся на "2025", где буква 'Y' встречается ≥ 140 раз, а подстрока "2025" — ровно 50 раз.
Решение двойным циклом:
max_len = 0
for i in range(len(s)):
for j in range(i + max_len, len(s)):
sub = s[i:j+1]
if sub.count('2025') > 50: break
if sub.count('2025') == 50 and sub[-4:] == '2025':
if sub.count('Y') >= 140:
max_len = max(max_len, len(sub))
Недостаток: Медленная работа на больших строках из-за повторных вызовов
.count()и квадратичной сложности.
Решение методом двух указателей:
- Идея: Динамически поддерживаем счётчики
ky(буква 'Y') иk2025при движении правого указателя. - Алгоритм:
- Двигаем
R. - Если встречаем 'Y' →
ky += 1. - Если встречаем окончание "2025" →
k2025 += 1. - Пока
k2025 > 50, двигаемL:- Если уходим от 'Y' →
ky -= 1. - Если уходим от "2025" →
k2025 -= 1.
- Если уходим от 'Y' →
- Если
k2025 == 50,ky >= 140и подстрока оканчивается на "2025" → обновляем максимум.
Результат: Решение работает значительно быстрее двойного цикла.
- Двигаем
Задача 2: Поиск минимальной подстроки
Условие: Найти минимальную подстроку, где "20" встречается ровно 26 раз, любая гласная — ровно 1 раз, и подстрока оканчивается на эту гласную.
Особенность для двух указателей:
- После того как основные условия выполнены (
k20 == 26иk_glasn == 1), нужно дополнительно сдвигать левый указательL, пока не нарушатся условия, чтобы минимизировать длину. - Это добавляет второй цикл
whileпосле основного условия.
Лайфхак: Для упрощения можно заменить все гласные на один символ (например, 'A').
Задача 3: Арифметические выражения (использование eval())
Условие: Найти максимальную подстроку, являющуюся корректным арифметическим выражением, значение которого — чётное число.
Нестандартный подход:
- Можно обойтись без сложных регулярных выражений.
- Перебираем подстроки двойным циклом и проверяем их валидность:
- Не начинается и не заканчивается на знак операции.
- Нет двух знаков подряд.
- Нет незначащих нулей (вида
+0или0...).
- Если подстрока валидна, вычисляем её значение с помощью
eval()и проверяем на чётность.
Внимание: eval()может выдать ошибку на некорректных выражениях (например,"05"), что помогает в отладке.
Задача 4: Арифметические выражения (два указателя)
Условие: Найти максимальную подстроку — корректную запись выражения, содержащего не более 40 чисел.
Хитрость: Вместо чисел проще считать знаки операций. Если чисел ≤ 40, то знаков ≤ 39.
Особенность: При обнаружении двух знаков подряд (++) последовательность гарантированно некорректна. В этом случае нужно "перепрыгнуть" — сдвинуть левый указатель L на позицию R + 1 и сбросить счётчики.
Задача 5: Поиск последовательностей ("в лоб")
Условие: Найти максимальную подстроку, состоящую из повторяющихся групп символов "КЛМН", где начальная и конечная группы могут быть неполными.
Нестандартное решение:
- Сначала находим максимальное количество полных групп "КЛМН", идущих подряд. Делается простым перебором: ищем в строке
"КЛМН"*nдля увеличивающегосяn, пока не перестанет находиться. - Получив число
n, вручную (или программно) проверяем, какие неполные группы могут примыкать к этой цепочке слева и справа, и добавляем их длину к ответу (n * 4 + длина_неполных_фрагментов).
Другие примеры конкретных задач
Задача с двумя одинаковыми буквами на концах:
- Внутри подстроки — только цифры, начало и конец — одинаковые буквы.
- Алгоритм (два указателя):
- Преобразовать все цифры в символ '0' для удобства.
- Когда
Rвстречает букву (символ не '0'), проверить, чтоS[L] == S[R]. - Если длина больше текущего максимума, обновить максимум и запомнить индекс начала (
ans = L). - После проверки переместить
Lна позициюR.
Задача с чётными цифрами и одной буквой внутри (двойной цикл):
- Первый и последний символы — чётные цифры, внутри — ровно одна (одинаковая) буква.
- Ключевые проверки: Первый/последний символ, уникальность букв в середине (через
set), количество цифр. При нарушении — раннийbreak.
Типичные ошибки, сложности и рекомендации
Сложности с буквами и условиями
- При использовании двух указателей иногда приходится "помнить" текущую букву для сравнения. Если буквы разные — может потребоваться сброс.
- Важно правильно определять условия для продолжения/сброса подстроки. Чем больше условий для раннего
break— тем быстрее работает алгоритм.
Индексы vs длина
- В некоторых задачах требуется найти индекс начала подстроки, а не её длину. Это меняет логику сохранения результата: нужно запоминать
L.
Выводы и практические советы
- Основной инструмент — два указателей. Постарайтесь отработать этот метод до автоматизма. Он закрывает большинство задач и является самым надёжным.
- Двойные циклы — запасной вариант. Используйте, если задача очевидно решается перебором, строки небольшие, или если не хватает времени на реализацию двух указателей.
- Не бойтесь нестандартных ходов. Иногда простой перебор (
"КЛМН"*n) или использование встроенных функций (eval()) дают быстрое решение. - Оптимизируйте проверки: Используйте
setдля проверки уникальности,replace()для замены символов (все цифры → '0'). - Тестируйте на больших данных. Всегда проверяйте производительность решения на файлах размером ~10 млн символов.
- Внимание к деталям. В задачах на минимальную подстроку нужен дополнительный цикл для "ужимания". В задачах на выражения — валидация на незначащие нули и двойные знаки.
- Практика и адаптация. Не надейтесь на шаблонные решения — нужно адаптировать алгоритм к конкретной задаче.