Задание 24: обработка символьной строки из файла

Работаем с очень длинной строкой символов: ищем самую длинную серию одинаковых букв и считаем вхождения шаблонов.

Серия (цепочка) — это максимальный участок строки из подряд идущих одинаковых символов.

Что проверяет задание 24

Задание 24 — повышенный уровень, 1 балл. К ЕГЭ прилагается файл с одной очень длинной строкой (часто из ограниченного набора букв, например только A, B, C). Типичные вопросы: «Какова длина самой длинной серии одинаковых символов?», «Сколько раз встречается заданная подстрока?», «Какова максимальная длина участка без буквы X?». Строка большая — нужен один проход по символам.

Теория: один проход с «текущей серией»

Чтобы найти самую длинную серию, идём по строке и поддерживаем длину текущей серии cur: если символ совпал с предыдущим — увеличиваем cur, иначе начинаем новую серию (cur = 1). Параллельно обновляем максимум. Это классический приём «сканирование с накоплением» за один проход.

cur = 1
для каждого символа, начиная со второго:
    если он равен предыдущему: cur += 1
    иначе: cur = 1
    обновить максимум max(best, cur)

Чтение строки из файла

with open("24.txt") as f:
    s = f.readline().strip()   # одна длинная строка без перевода в конце

Разбор примера

Дана строка из букв A, B, C. Нужно найти длину самой длинной серии одинаковых букв и саму эту букву. Возьмём строку AABBBCCCCABABBBBBA.

Решение на Python

s = "AABBBCCCCABABBBBBA"   # имитация строки из файла

best_len = 1          # длина самой длинной серии
best_ch = s[0]        # буква этой серии
cur = 1               # длина текущей серии

for i in range(1, len(s)):
    if s[i] == s[i - 1]:
        cur += 1
        if cur > best_len:
            best_len = cur
            best_ch = s[i]
    else:
        cur = 1

print("Длина макс. серии:", best_len)
print("Буква серии:", best_ch)

Вывод:

Длина макс. серии: 5
Буква серии: B

Самая длинная серия — пять букв B в конце (BBBBB). Серия CCCC длиной 4 — короче. Один проход по строке решает задачу даже для миллионов символов.

Подсчёт вхождений подстроки

Часто спрашивают, сколько раз встречается шаблон, например «AB». Метод строки count считает непересекающиеся вхождения слева направо.

s = "ABABABXABAB"
print("Вхождений 'AB':", s.count("AB"))
print("Вхождений 'ABA':", s.count("ABA"))   # непересекающиеся!

Вывод:

Вхождений 'AB': 5
Вхождений 'ABA': 2

Обратите внимание: count не считает пересекающиеся вхождения. «ABABA» содержит «ABA» дважды по позициям, но count найдёт только одно (после совпадения он продолжает с конца найденного). Если в задаче нужны пересекающиеся вхождения — считайте циклом по всем позициям.

s = "ABABABA"
pattern = "ABA"
overlapping = sum(1 for i in range(len(s) - len(pattern) + 1)
                  if s[i:i + len(pattern)] == pattern)
print("Пересекающихся вхождений 'ABA':", overlapping)

Вывод:

Пересекающихся вхождений 'ABA': 3

В строке «ABABABA» подстрока «ABA» начинается на позициях 0, 2 и 4 — три раза, если разрешено перекрытие. count даёт только непересекающиеся, поэтому всегда уточняйте формулировку: «сколько раз встречается» обычно означает непересекающиеся, но «на скольких позициях начинается» — это перекрытия.

Самый длинный участок без заданной буквы

Ещё один частый вопрос: «Какова наибольшая длина участка, не содержащего букву X?» Это та же идея «текущей длины», но сбрасываем счётчик не при смене символа, а при встрече запретной буквы.

s = "AABXCCCCXBBXCC"   # ищем самый длинный участок без 'X'
forbidden = "X"

best = 0     # лучшая длина участка без X
cur = 0      # длина текущего участка без X
for ch in s:
    if ch == forbidden:
        cur = 0              # встретили X — участок прерван
    else:
        cur += 1
        if cur > best:
            best = cur
print("Самый длинный участок без 'X':", best)

Вывод:

Самый длинный участок без 'X': 4

Между двумя буквами X стоит «CCCC» длиной 4 — это и есть ответ. Обратите внимание: счётчик cur сбрасывается ровно на запретной букве, а максимум обновляется на каждом шаге роста. Тот же шаблон годится для «участок без гласных», «без повторов» и подобных формулировок — меняется только условие сброса.

Замена и подсчёт через метод count для одного символа

Если нужно просто сосчитать, сколько раз встречается один символ (а не подстрока и не серия), хватит str.count или сравнения в генераторе.

s = "AABBBCCCCABABBBBBA"
print("Букв 'B' всего:", s.count("B"))
print("Букв 'C' всего:", sum(1 for ch in s if ch == "C"))

Вывод:

Букв 'B' всего: 9
Букв 'C' всего: 4

Типичные ошибки

  • Не обновляют максимум вовремя. Максимум проверяют на каждом шаге увеличения серии, а не только в конце.
  • Путают пересекающиеся и непересекающиеся вхождения. count — непересекающиеся; для пересекающихся нужен явный цикл.
  • Забывают strip() при чтении. Перевод строки в конце может исказить последнюю серию.
  • Стартуют максимум с нуля при пустой обработке. Для непустой строки минимальная серия — 1, начинайте с 1.

Итог

  • Самая длинная серия — один проход с переменной текущей серии и обновлением максимума.
  • Для подсчёта подстрок str.count считает непересекающиеся вхождения; пересекающиеся — циклом по позициям.
  • При чтении строки делайте strip(), чтобы убрать перевод строки.
Проверьте себя
1. Как найти длину самой длинной серии одинаковых символов за один проход?
AОтсортировать строку
BИдти по символам, наращивая длину текущей серии и обновляя максимум
CПосчитать общее число каждого символа
DПеревернуть строку
2. Сколько непересекающихся вхождений 'ABA' найдёт 'ABABA'.count('ABA')?
A2
B1
C3
D0
3. Когда нужно считать вхождения подстроки циклом по позициям, а не через count?
AКогда строка короткая
BКогда нужны ПЕРЕСЕКАЮЩИЕСЯ вхождения
CНикогда
DКогда символы только латинские
Поддержать проект