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

3. Повторяющиеся паттерны

Паттерн (ABC)+ — повторение группы ABC один или более раз.

s = "XYZABCABCABCXYZ"
re.findall(r'(ABC)+', s)  # ['ABC'] — возвращает последнюю группу!

# Чтобы получить всю цепочку:
re.findall(r'(?:ABC)+', s)  # ['ABCABCABC'] — (?:...) не захватывает

В примере (?:ABC)+ квантификатор + применяется ко всей группе ABC, но поскольку группа незахватывающая, re.findall() возвращает всё найденное совпадение целиком, а не содержимое группы. Это полезно, когда скобки нужны для структурирования выражения, но захват отдельных фрагментов не требуется.
 


Пример 1: (?:ABC)*(?:AB?)?
s = "XYZABCABCABXYZABCAYZ"
re.findall(r'(?:ABC)*(?:AB?)?', s) # много пустых...

Проблема: Этот паттерн создает множество пустых совпадений, потому что оба квантификатора * и ? делают совпадение необязательным. Паттерн может совпасть с пустой строкой в любой позиции:​

  • (?:ABC)* — ноль или больше повторений ABC

  • (?:AB?)? — опционально A или AB

  • Оба элемента необязательны, поэтому паттерн совпадает везде, включая пустые позиции между символами



Пример 2: A(?:BCA)*B?C?
re.findall(r'A(?:BCA)*B?C?', s)

Логика: Более строгий паттерн, требующий обязательного начала с A:​

  • A — обязательная буква A (якорь паттерна)

  • (?:BCA)* — ноль или больше повторений BCA (переставленный фрагмент)

  • B?C? — опционально B и/или C для неполного последнего фрагмента

Недостаток: Паттерн использует BCA вместо ABC, что меняет логику разбора и может работать некорректно для исходной задачи.
 

Пример 3: (?:ABC)+A?B?
re.findall(r'(?:ABC)+A?B?', s)

Оптимальное решение:

  • (?:ABC)+ — одно или больше повторений полного фрагмента ABC (обязательно хотя бы один)​

  • A?B? — опционально добавляются A или AB для неполного последнего фрагмента

  • Квантификатор + гарантирует, что паттерн найдет только реальные цепочки, начинающиеся с хотя бы одного полного ABC, без пустых совпадений​

Этот вариант находит цепочки типа ABCABCABCABCABCAABCABCAB и т.д., что соответствует задаче поиска последовательностей с возможно неполным последним фрагментом.


Пример решения

import re

with open('input.txt') as f:
    s = f.read().strip()

# Цепочки вида XYXY... (последний фрагмент может быть неполным)
# XY, XYX, XYXY, XYXYX, ...
matches = re.findall(r'(?:XY)+X?', s)
print(max(len(m) for m in matches) if matches else 0)
Печать