'*' означает 0 или более вхождений
«AA» должен сделать трюк.
Вопрос в том, хотите ли вы, чтобы вещь соответствовала 'AAA'. В этом случае вам придется сделать что-то вроде:
r = re.compile('(^|[^A])(AA)+(?!A)',)
r.search(p)
Это сработало бы для совпадения четного (и только четного) числа 'A'.
Теперь, если вы хотите сопоставить «если есть любое четное количество последующих букв», это бы сработало:
re.compile(r'(.)\1')
Однако это не исключает «странных» случаев. Но из твоего вопроса не ясно, действительно ли ты этого хочешь.
Обновление:
Это работает для вас тестовых случаев:
re.compile('^([^A]*)AA([^A]|AA)*$')