Соответствие на повторных подстроках в regex

Я сравнил решение с perfplot (мой небольшой проект для таких целей) и обнаружил, что ответ Нолена с наибольшим количеством голосов также самый медленный.

Оба ответа, предоставленные Сковородкиным , намного быстрее. (Обратите внимание на логарифмическую шкалу.)

enter image description here

Чтобы создать сюжет:

import perfplot
import collections


def nolen(number):
    answer = set()
    answer.add((number, ))
    for x in range(1, number):
        for y in nolen(number - x):
            answer.add(tuple(sorted((x, ) + y)))
    return answer


def skovorodkin(n):
    return set(skovorodkin_yield(n))


def skovorodkin_yield(n, I=1):
    yield (n,)
    for i in range(I, n//2 + 1):
        for p in skovorodkin_yield(n-i, i):
            yield (i,) + p


def accel_asc(n):
    return set(accel_asc_yield(n))


def accel_asc_yield(n):
    a = [0 for i in range(n + 1)]
    k = 1
    y = n - 1
    while k != 0:
        x = a[k - 1] + 1
        k -= 1
        while 2 * x <= y:
            a[k] = x
            y -= x
            k += 1
        l = k + 1
        while x <= y:
            a[k] = x
            a[l] = y
            yield tuple(a[:k + 2])
            x += 1
            y -= 1
        a[k] = x + y
        y = x + y - 1
        yield tuple(a[:k + 1])


def mct(n):
    partitions_of = []
    partitions_of.append([()])
    partitions_of.append([(1,)])
    for num in range(2, n+1):
        ptitions = set()
        for i in range(num):
            for partition in partitions_of[i]:
                ptitions.add(tuple(sorted((num - i, ) + partition)))
        partitions_of.append(list(ptitions))
    return partitions_of[n]


perfplot.show(
    setup=lambda n: n,
    kernels=[
        nolen,
        mct,
        skovorodkin,
        accel_asc,
        ],
    n_range=range(1, 17),
    logy=True,
    # https://stackoverflow.com/a/7829388/353337
    equality_check=lambda a, b:
        collections.Counter(set(a)) == collections.Counter(set(b)),
    xlabel='n'
    )

25
задан Whatsit 29 May 2009 в 21:11
поделиться

4 ответа

Использовать группы захвата и обратные ссылки.

/^(.{3}).*\1$/

\ 1 относится к тому, что соответствует содержимому первой группы захвата (содержимое () ) . Регулярные выражения в большинстве языков допускают нечто подобное.

28
ответ дан 28 November 2019 в 20:51
поделиться

Для тех же символов в начале и в конце :

/^(.{3}).*\1$/

Это обратная ссылка .

3
ответ дан 28 November 2019 в 20:51
поделиться

Вам нужны обратные ссылки . Идея состоит в том, чтобы использовать группу захвата для первого бита, а затем возвращаться к ней, когда вы пытаетесь сопоставить последний бит. Вот пример соответствия пары начальных и конечных тегов HTML (из приведенной ранее ссылки):

 <([AZ] [A-Z0-9] *) \ b [^>] *>. *? < / \ 1>

Это регулярное выражение содержит только одну пару круглых скобок, в которой записана строка, соответствующая [AZ] [A-Z0-9] * , в первой обратной ссылке. Эта обратная ссылка повторно используется с \ 1 (обратная косая черта). / перед ним - это просто косая черта в закрывающем теге HTML, который мы пытаемся сопоставить.

Применяем это к вашему случаю:

/^(.{3}).*\1$/

(Да, это регулярное выражение, которое опубликовал Брайан Карпер. Просто существует не так много способов сделать это.)

Подробное объяснение для потомков (пожалуйста, не обижайтесь, если оно ниже вас):

  • ^ соответствует началу строки.
  • (. {3}) захватывает три символа любого типа и сохраняет их в группе для последующего использования.
  • . * соответствует чему-либо как можно дольше. (Тебе все равно, что? s в середине строки.)
  • \ 1 соответствует группе, захваченной на шаге 2.
  • $ соответствует концу строки.
16
ответ дан 28 November 2019 в 20:51
поделиться

Это работает:

my $test = 'abcabc';
print $test =~ m/^([a-z]{3}).*(\1)$/;

Для сопоставления начала и конца вы должны добавить якоря ^ и $ .

2
ответ дан 28 November 2019 в 20:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: