Как проверить, что строка является палиндромом с помощью регулярных выражений?

79
задан Community 23 May 2017 в 11:54
поделиться

15 ответов

Ответ на этот вопрос - то, что "это невозможно". А именно, интервьюер задается вопросом, обратили ли Вы внимание в своем вычислительном классе теории.

В Вашем вычислительном классе теории Вы узнали о конечных автоматах. Конечный автомат состоит из узлов и краев. Каждый край аннотируется буквой от конечного алфавита. Один или несколько узлов являются специальными узлами "принятия", и один узел является узлом "запуска". Поскольку каждая буква читается из пообещанного, мы пересекаем данный край в машине. Если мы заканчиваем в состоянии принятия тогда, мы говорим, что машина "принимает" то слово.

регулярное выражение А может всегда переводиться в эквивалентный конечный автомат. Таким образом, тот, который принимает и отклоняет те же слова как регулярное выражение (в реальном мире, некоторые regexp языки допускает произвольные функции, они не рассчитывают).

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

a^x b a^x (например, ткань из верблюжьей шерсти, aabaa, aaabaaa, aaaabaaaa....)

, где a^x является повторными x временами. Это требует, по крайней мере, x узлов, потому что, после наблюдения 'b' мы должны считать назад x времена, чтобы удостовериться, что это - палиндром.

Наконец, возвращаясь к исходному вопросу, Вы могли сказать интервьюеру, что можно записать регулярное выражение, которое принимает все палиндромы, которые меньше, чем некоторая конечная фиксированная длина. Если будет когда-нибудь реальное приложение, которое требует палиндромов идентификации тогда, то оно не будет почти наверняка включать произвольно длинные, таким образом этот ответ показал бы, что можно дифференцировать теоретическую невозможность от реальных приложений. Однако, фактический regexp был бы довольно длинен, намного дольше, чем эквивалентная программа с 4 строками (легкое осуществление для читателя: запишите программу, которая определяет палиндромы).

132
ответ дан Jose M Vidal 24 November 2019 в 10:02
поделиться

Я объяснил бы интервьюеру, что язык, состоящий из палиндромов, не является регулярным языком, но вместо этого контекстно-свободный.

регулярное выражение, которое соответствовало бы всем палиндромам, будет бесконечно . Вместо этого я предложил бы, чтобы он ограничил себя любым максимальный размер палиндромов для принятия; или если все палиндромы необходимы использование в минимуме некоторый тип NDPA или просто используют метод реверсирования/равняться простой строки.

1
ответ дан Flame 24 November 2019 в 10:02
поделиться

что-то можно сделать с жемчугом: http://www.perlmonks.org/?node_id=577368

1
ответ дан Zsolt Botykai 24 November 2019 в 10:02
поделиться

Как указано ZCHudson, определите, является ли что-то палиндромом, не может быть сделан с обычным regexp, поскольку набор палиндрома не является регулярным языком.

я полностью не соглашаюсь с Airsource Ltd , когда он говорит, что "это не possibles", не вид ответа, который ищет интервьюер. Во время моего интервью я приезжаю в этот вид вопроса, когда я сталкиваюсь с хорошим кандидатом, чтобы проверить, может ли он найти правильный аргумент, когда мы предложили ему сделать что-то не так. Я не хочу нанимать кого-то, кто попытается сделать что-то неправильный путь, если он будет знать лучший.

1
ответ дан Community 24 November 2019 в 10:02
поделиться

На самом деле легче сделать это с обработкой строк, а не регулярными выражениями:

bool isPalindrome(String s1)

{

    String s2 = s1.reverse;

    return s2 == s1;
}

я понимаю, что это действительно не отвечает на вопрос интервью, но Вы могли использовать его, чтобы показать, как Вы знаете лучший способ сделать задачу, и Вы не типичный "человек с молотком, который рассматривает каждую проблему как гвоздь".

2
ответ дан dbr 24 November 2019 в 10:02
поделиться

В Perl (см. также ответ Zsolt Botykai ):

$re = qr/
  .                 # single letter is a palindrome
  |
  (.)               # first letter
  (??{ $re })??     # apply recursivly (not interpolated yet)
  \1                # last letter
/x;

while(<>) {
    chomp;
    say if /^$re$/; # print palindromes
}
2
ответ дан Community 24 November 2019 в 10:02
поделиться

Относительно выражения PCRE (от MizardX):

/^(.) (? 1) \2 |. $?) /

Вы протестировали его? На моем PHP 5.3 под XP Победы Pro это перестало работать на: aaaba На самом деле, я изменил выражение выражения немного, для чтения:

/^(.) (? 1) *\2 |. $?) /

я думаю, что происходит, то, что, в то время как внешняя пара символов привязываются, остающиеся внутренние не. Это - не совсем целый ответ, потому что, в то время как он неправильно передает "aaaba" и "aabaacaa", он действительно перестал работать правильно на "aabaaca".

интересно, делает ли там fixup для этого, и также, пример Perl (Sebastian JF / Zsolt), проходят мои тесты правильно?

Csaba Gabor из Вены

3
ответ дан 24 November 2019 в 10:02
поделиться

В зависимости от того, насколько уверенный Вы, я дал бы этот ответ:

я не сделал бы этого с регулярным выражением. Это не соответствующее использование регулярных выражений.

10
ответ дан Jon Skeet 24 November 2019 в 10:02
поделиться

Вот один для обнаружения палиндромов с 4 буквами (например: дело), для любого типа символа:

\(.\)\(.\)\2\1

Вот один для обнаружения палиндромов с 5 буквами (например: радар), проверяя на буквы только:

\([a-z]\)\([a-z]\)[a-z]\2\1

, Таким образом, кажется, что нам нужен различный regex для каждой возможной длины слова. Это сообщение в списке рассылки Python включает некоторые детали относительно почему (Конечные автоматы и насосная лемма).

11
ответ дан FOR 24 November 2019 в 10:02
поделиться

С Perl regex:

/^((.)(?1)\2|.?)$/

, Хотя, как многие указали, это нельзя считать регулярным выражением, если Вы хотите быть строгими. Регулярные выражения не поддерживает рекурсию.

24
ответ дан Markus Jarderot 24 November 2019 в 10:02
поделиться

Это не возможно. Палиндромы не определяются регулярным языком. (См., я, DID изучает что-то в вычислительной теории)

28
ответ дан Dima 24 November 2019 в 10:02
поделиться

В то время как механизм PCRE действительно поддерживает рекурсивные регулярные выражения (см. ответ Peter Krauss ), Вы не можете использовать regex на механизм ICU (как используется, например, Apple) для достижения этого без дополнительного кода. Необходимо будет сделать что-то вроде этого:

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

$a = "teststring";
while(length $a > 1)
{
   $a =~ /(.)(.*)(.)/;
   die "Not a palindrome: $a" unless $1 eq $3;
   $a = $2;
}
print "Palindrome";
41
ответ дан Airsource Ltd 24 November 2019 в 10:02
поделиться

Небольшое уточнение метода Airsource Ltd в псевдокоде:

WHILE string.length > 1
    IF /(.)(.*)\1/ matches string
        string = \2
    ELSE
        REJECT
ACCEPT
0
ответ дан 24 November 2019 в 10:02
поделиться

Как уже говорили некоторые, не существует единого регулярного выражения, которое бы сразу же обнаружило общий палиндром, но если вы хотите обнаружить палиндромы до определенной длины, вы можете использовать что-нибудь например

(.?)(.?)(.?)(.?)(.?).?\5\4\3\2\1
7
ответ дан 24 November 2019 в 10:02
поделиться

Да, вы можете сделать это в .Net!

(?<N>.)+.?(?<-N>\k<N>)+(?(N)(?!))

Вы можете проверить это здесь! Это замечательный пост!

10
ответ дан 24 November 2019 в 10:02
поделиться
Другие вопросы по тегам:

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