Короткие Повторяющиеся Подстроки
Я ищу эффективный способ извлечь самую короткую повторяющуюся подстроку. Например:
input1 = 'dabcdbcdbcdd'
ouput1 = 'bcd'
input2 = 'cbabababac'
output2 = 'ba'
Я был бы признателен за любой ответ или информацию, связанную с проблемой.
кроме того, в этот пост люди предполагают, что мы можем использовать регулярные выражения, как
re=^(.*?)+$
чтобы найти наименьший повторяющийся шаблон в строке. Но такое выражение не работает в Python и всегда возвращает мне несоответствие (я новичок в Python и может быть, я что-то упустил?).
--- продолжение ---
здесь критерий состоит в том, чтобы искать кратчайший шаблон без перекрытия, длина которого больше единицы и имеет самую длинную общую длину.
2 ответов
быстрое исправление для этого шаблона может быть
(.+?)+
ваше регулярное выражение не удалось, потому что оно закрепило повторяющуюся строку в начале и конце строки, позволяя только строки, такие как abcabcabc
а не xabcabcabcx
. Кроме того, минимальная длина повторяющейся строки должна быть 1, а не 0 (или любая строка будет соответствовать), поэтому .+?
вместо .*?
.
В Python:
>>> import re
>>> r = re.compile(r"(.+?)+")
>>> r.findall("cbabababac")
['ba']
>>> r.findall("dabcdbcdbcdd")
['bcd']
но имейте в виду, что это регулярное выражение найдет только неперекрывающееся повторение соответствует, поэтому в последнем примере решение d
не будет найден, хотя это самая короткая повторяющаяся строка. Или посмотрите этот пример: здесь он не может найти abcd
потому что abc
часть первая abcd
был использован в первом матче):
>>> r.findall("abcabcdabcd")
['abc']
кроме того, он может вернуть несколько матчей, поэтому вам нужно будет найти самый короткий на втором шаге:
>>> r.findall("abcdabcdabcabc")
['abcd', 'abc']
лучшее решение:
чтобы двигатель также найти перекрывающиеся матчи, используйте
(.+?)(?=)
это найдет некоторые строки дважды или более, если они повторяются достаточно раз, но он, безусловно, найдет все возможные повторяющиеся подстроки:
>>> r = re.compile(r"(.+?)(?=)")
>>> r.findall("dabcdbcdbcdd")
['bcd', 'bcd', 'd']
поэтому вы должны отсортировать результаты по длине и вернуть самый короткий:
>>> min(r.findall("dabcdbcdbcdd") or [""], key=len)
'd'
на or [""]
(спасибо Дж. Ф. Себастьян!) гарантирует, что нет ValueError
срабатывает, если нет совпадений вообще.
^
матчи в начале строки. В вашем примере повторяющиеся подстроки не начинаются с самого начала. Похожие на $
. Без ^
и $
шаблон .*?
всегда соответствует пустой строке. демо:
import re
def srp(s):
return re.search(r'(.+?)+', s).group(1)
print srp('dabcdbcdbcdd') # -> bcd
print srp('cbabababac') # -> ba
хотя он не находит самую короткую подстроку.