Як перевірити, що рядок є паліндромом, використовуючи регулярні вирази?


93

Це було питання інтерв’ю, на яке я не зміг відповісти:

Як перевірити, що рядок є паліндромом, використовуючи регулярні вирази?

ps Уже є запитання " Як перевірити, чи вказаний рядок паліндром? ", і воно дає багато відповідей різними мовами, але жодної відповіді, що використовує регулярні вирази.


1
stackoverflow.com/questions/3644266/… може дати уявлення.
Прахар

2
На сьогоднішній день (2018) та хто шукає "регулярний вираз паліндрому", дивіться дискусію про PCRE, що підтримує рекурсивні шаблони за посиланням Прахара, та мій рекурсивний регулярний вираз нижче, з порівняннями .
Пітер Краус,

Відповіді:


151

Відповідь на це питання полягає в тому, що "це неможливо". Більш конкретно, інтерв’юер цікавиться, чи звернули ви увагу на уроці теорії обчислень.

На уроці обчислювальної теорії ви дізналися про кінцеві автомати. Кінцевий автомат складається з вузлів і ребер. Кожне ребро коментується літерою з кінцевого алфавіту. Один або декілька вузлів є спеціальними "приймаючими" вузлами, а один вузол є "стартовим" вузлом. Оскільки кожна буква читається з даного слова, ми проходимо через даний край у машині. Якщо ми опиняємося в стані прийняття, ми говоримо, що машина "приймає" це слово.

Регулярний вираз завжди можна перевести в еквівалентний кінцевий автомат. Тобто той, який приймає та відкидає ті самі слова, що й регулярний вираз (у реальному світі деякі мови регулярних виразів дозволяють використовувати довільні функції, вони не враховуються).

Неможливо побудувати кінцевий автомат, який приймає всі паліндроми. Доказ покладається на факти, що ми можемо легко побудувати рядок, що вимагає довільно великої кількості вузлів, а саме рядок

a ^ xba ^ x (напр., aba, aabaa, aaabaaa, aaaabaaaa, ....)

де a ^ x - повторене x разів. Для цього потрібно принаймні x вузлів, тому що, побачивши 'b', ми маємо відрахувати x разів, щоб переконатися, що це паліндром.

Нарешті, повертаючись до початкового питання, ви можете сказати інтерв'юеру, що можете написати регулярний вираз, який приймає всі паліндроми, менші за деяку кінцеву фіксовану довжину. Якщо коли-небудь існує реальний додаток, який вимагає ідентифікації паліндромів, тоді він майже напевно не включатиме довільно довгі, тому ця відповідь покаже, що ви можете диференціювати теоретичні неможливості від реальних програм. Тим не менше, фактичний регулярний вираз був би досить довгим, набагато довшим, ніж еквівалентна 4-рядкова програма (легка вправа для читача: написати програму, яка ідентифікує паліндроми).


6
@SteveMoser У Ruby 1.9.x регулярні вирази перестали бути регулярними (у розумінні теорії автоматів), і, отже, такі речі, як перевірка паліндромів, можливі. Однак для цілей і цілей паліндроми не можна перевіряти за допомогою регулярного регулярного виразу (має сенс?).

1
@SteveMoser Тут є хороший запис механізму регулярних виразів Ruby ( >=1.9) тут

@ Джон прав, тож у контексті питання Хосе має рацію, а hqt - неправильно.
Steve Moser

2
В академічному плані регулярний вираз має певні межі (визначає DFA). Насправді багато механізмів регулярних виразів (Perl та його родичі в першу чергу) підтримують зворотні посилання, які порушують академічне визначення (стаючи NFA або навіть ширше). Отже, це запитання має різні відповіді залежно від того, якою була система допиту.
jiggy

Під час усного іспиту zou повинен відповісти "formalz неможливо", але ви повинні зазначити, що деякі двигуни регулярних виразів це дозволяють.
Олівер А.

46

Хоча механізм PCRE підтримує рекурсивні регулярні вирази (див . Відповідь Пітера Краусса ), ви не можете використовувати регулярний вираз на ICU (як, наприклад, Apple), щоб досягти цього без додаткового коду. Вам потрібно буде зробити щось подібне:

Це виявляє будь-який паліндром, але вимагає циклу (що буде потрібно, оскільки регулярні вирази не можуть рахуватися).

$a = "teststring";
while(length $a > 1)
{
   $a =~ /(.)(.*)(.)/;
   die "Not a palindrome: $a" unless $1 eq $3;
   $a = $2;
}
print "Palindrome";

4
Хороша відповідь. Питання не вимагало жодного регулярного виразу, який виявляє паліндром прямо з коробки - він просто задавав метод виявлення паліндромів, який використовує регулярні вирази. Вітаємо з вашим розумінням, щоб поглянути на це так.
Стюарт

1
Див. Також найпростішу відповідність (без маніпулювання рядками) з використанням лише одного регулярного виразу, stackoverflow.com/a/48608623/287948
Пітер Краус

Дякую @PeterKrauss. Не знав, що PCRE має рекурсію. Посилався на свою відповідь.
Airsource Ltd

32

Це неможливо. Паліндроми не визначаються звичайною мовою. (Дивіться, Я ВЧИЛ дещо в обчислювальній теорії)


2
Більшість механізмів регулярних виразів охоплюють більше, ніж регулярні мови (наприклад, net може фіксувати відповідні дужки). Лише стандартні регулярні вирази обмежені звичайними мовами.
Сантьяго Палладіно

У запитанні все-таки використовувався термін "регулярний вираз" ... тому відповідь ZCHudson є правильною.
paxos1977

2
@austirg: Відповідь ZCHudson правильна, але неповна. Регулярні вирази, що використовуються в сучасних мовах програмування, та регулярні вирази, що використовуються на теоретичних заняттях з CS, - це різні звірі. Цей термін - лише історична спадщина. Дивіться stackoverflow.com/questions/233243#235199 та мою відповідь.
jfs

2
@JF Себастьян - я мав би з цим погодитися з austirg. Коли термін регулярний вираз використовується без згаданої конкретної мови програмування, застосовується визначення comp. Не всі мови, які підтримують регулярні вирази, можуть це зробити, тому ми не повинні вважати, що використовується тут.
Ронтолог

@Rontologist: Я не бачу обмежень щодо вибору мови програмування у цьому питанні, тому будь-яка мова дозволена. Подивіться праворуч: що означає "регулярний вираз" у відповідних питаннях? Чи згадується конкретна мова програмування в будь-якій з них?
jfs

27

З регулярним виразом Perl:

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

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


це не працює в PCRE (не відповідає "ababa"), але працює в Perl 5.10
newacct

Ти правий. Здається, PCRE трактує рекурсію як атомну групу, тоді як Perl дозволяє зворотне відстеження всередині неї. Я не думаю, що це можливо зробити в PCRE.
Markus Jarderot

1
Дивно, але це не працює для нелатинських мов, наприклад вірменської мови.
Темуджин

3
@Temujin Це відбувається тому, що символи Unicode відповідають закодованим байтам (додайте /uмодифікатор ), або через символи комбінатора. (Замінити .з керуючою \Xпослідовністю ).
Markus Jarderot

1
Мій шаблон не працює в PCRE. Це працює в Perl. Ваш шаблон не вдається повторити підрядки. Наприклад abababa. Неможливо змусити його працювати з рекурсією для кожного вводу при використанні механізмів регулярних виразів на основі PCRE. Regex Casimirs використовує інший підхід, використовуючи ітерацію та мінливий стан, і є досить захоплюючим.
Markus Jarderot

15

Ось один із них, щоб виявити 4-літерні паліндроми (наприклад: діло) для будь-якого типу символів:

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

Ось один для виявлення 5-літерних паліндромів (наприклад: радар), перевіряючи лише наявність літер:

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

Тож, здається, нам потрібен різний регулярний вираз для кожної можливої ​​довжини слова. Ця публікація у списку розсилки Python містить деякі подробиці щодо того, чому (кінцеві автомати та лемма про накачування).


14

Залежно від того, наскільки ви впевнені в собі, я дав би таку відповідь:

Я б не робив цього з регулярним виразом. Це не належне використання регулярних виразів.


3
Я сподіваюся, ви дасте трохи більше пояснень, щоб показати, що ви справді розумієте обмеження регулярного виразу. Вашу просту відповідь можна сприймати як "Я тупий".
Скотт Вегнер,

Звідси речення залежності, яке він дав.
Уілл Бікфорд,

13

Так , ви можете це зробити в .Net!

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

Ви можете перевірити це тут ! Це чудова публікація!


Вся суть Regex зі смаком .NET полягає в тому, що вони не є регулярними, оскільки вони не є автоматичними системами з кінцевим станом; вони насправді не є регулярними виразами в теоретичному розумінні.
кішка

12

StackOverflow наповнений відповідями на кшталт "Регулярні вирази? Ні, вони їх не підтримують. Вони не можуть це підтримати.".

Істина полягає в тому, що регулярні вирази вже не мають нічого спільного з регулярними граматиками . Сучасні регулярні вирази мають такі функції, як рекурсія та балансування груп, і доступність їх реалізації постійно зростає (наприклад, див. Приклади Ruby тут). На мій погляд, притримування старої віри, що регулярні вирази у нашій галузі - це що завгодно, але не концепція програмування, є просто контрпродуктивним. Замість того, щоб ненавидіти їх за вибір слова, яке вже не є найбільш доречним, нам час прийняти речі і рухатися далі.

Ось цитата з Ларрі Волла , самого творця Perl:

(...) загалом пов'язані з тим, що ми називаємо "регулярними виразами", які лише незначно пов'язані з реальними регулярними виразами. Тим не менше, цей термін виріс завдяки можливостям наших механізмів узгодження шаблонів, тому я не буду намагатися боротися з мовною необхідністю тут. Однак я, як правило, називатиму їх "регулярними виразами" (або "регулярними виробами", коли я перебуваю в англосаксонському настрої).

А ось пост в блозі на одному з основних розробників РНР :

Оскільки стаття була досить довгою, ось короткий зміст основних моментів:

  • «Регулярні вирази», що використовуються програмістами, мають дуже мало спільного з початковим поняттям регулярності в контексті теорії формальної мови.
  • Регулярні вирази (принаймні PCRE) можуть відповідати всім контекстовим мовам. Як такі, вони також можуть відповідати добре сформованому HTML і майже всім іншим мовам програмування.
  • Регулярні вирази можуть відповідати принаймні деяким контекстно-залежним мовам.
  • Відповідність регулярних виразів повна NP. Таким чином, ви можете вирішити будь-яку іншу проблему NP за допомогою регулярних виразів.

Як сказано, ви можете зіставити паліндроми з регулярними виразами, використовуючи це:

^(?'letter'[a-z])+[a-z]?(?:\k'letter'(?'-letter'))+(?(letter)(?!))$

... що, очевидно, не має нічого спільного із звичайними граматиками.
Більше інформації тут: http://www.regular-expressions.info/balancing.html


9

Як вже говорили деякі, не існує жодного регулярного виразу, який би виявив загальний паліндром нестандартно, але якщо ви хочете виявити паліндроми до певної довжини, ви можете використовувати щось на зразок

(.?)(.?)(.?)(.?)(.?).?\5\4\3\2\1

7

Це можна зробити в Perl зараз. Використання рекурсивного посилання:

if($istr =~ /^((\w)(?1)\g{-1}|\w?)$/){
    print $istr," is palindrome\n";
}

змінено на основі останньої частини http://perldoc.perl.org/perlretut.html


6

У рубіні ви можете використовувати іменовані групи захоплення. так що щось подібне буде працювати -

def palindrome?(string)
  $1 if string =~ /\A(?<p>| \w | (?: (?<l>\w) \g<p> \k<l+0> ))\z/x
end

спробуйте, це працює ...

1.9.2p290 :017 > palindrome?("racecar")
 => "racecar" 
1.9.2p290 :018 > palindrome?("kayak")
 => "kayak" 
1.9.2p290 :019 > palindrome?("woahitworks!")
 => nil 

1
Названі групи захоплення не є строго регулярними виразами. willamette.edu/~fruehr/LLC/lab5.html
Стів Мозер

2
Ви праві. Саме тому я зазначив, що вам доведеться використовувати іменовані групи захоплення.
Тейлор

Чи міг би хтось випадково пояснити, що РЕ персонаж за символом для новачка? Я розумію все наступне (коми відокремлюють "атоми") /, \ A, (, |, \ w, |, (, (, \ w,),),), \ z, /, x, але я не розумію не розумію жодного з цих? <p>,?:,? <l>, \ g <p>, \ k <l + 0>, і я використовую rubular.com для допомоги, і, схоже, розумію RE ( природно), але це не допомагає мені це побачити, і навіть "Повний посібник із регулярних виразів Ruby див. у" Кірці ". не допомагає, оскільки сайт, пов’язаний із „Кіркою”, не пояснює атоми, які я не можу зрозуміти. Я знаю ? ЗА НАСТУПНИМИ збігами Нуль або один з a, але? перед персонажем?
Кевін Форд, підводник

Ах, названі групи захоплення ! Приємно. @SteveMoser це недіюче посилання, але я знайшов інше . Дякую Тейлору, що згадав їх, бо в іншому випадку, я б навіть не уявляв, що мається на увазі? <p> і? <l> і?: (Група захоплення не захоплює) та \ g <p> та \ k <l + 0>. Я все ще не можу зрозуміти що? <p> | це хоча. Не | означає "або"? Я не можу знайти документацію щодо цього використання труби в РЕ. Я все одно був би радий побачити детальне пояснення цього дуже приємного RE.
Кевін Форд, підводник

5

Насправді це простіше зробити за допомогою маніпулювання рядками, а не за допомогою регулярних виразів:

bool isPalindrome(String s1)

{

    String s2 = s1.reverse;

    return s2 == s1;
}

Я усвідомлюю, що це насправді не відповідає на запитання співбесіди, але ви можете використати це, щоб продемонструвати, як ви знаєте кращий спосіб виконання завдання, і ви не типовий "людина з молотком, котра сприймає кожну проблему як цвях . "


Хоча я дуже люблю цю відповідь, я думаю, ви отримаєте додаткові бали, використовуючи BreakIterator, щоб правильно розділити рядок на візуальні символи.
Трейказ

5

Ось моя відповідь на Regex Golf 5-го рівня (Чоловік, план). Він працює до 7 символів за допомогою Regexp браузера (я використовую Chrome 36.0.1985.143).

^(.)(.)(?:(.).?\3?)?\2\1$

Ось одна довжина до 9 символів

^(.)(.)(?:(.)(?:(.).?\4?)?\3?)?\2\1$

Щоб збільшити максимальну кількість символів, для яких це працювало, ви б неодноразово замінювали .? з (?: (.).? \ n?)? .


1
У мене вийшов той, де трохи менше символів, ^ (.) (.) (.)?.? \ 3 \ 2 \ 1 $
Бен Елліс,


Чому у решти людей 13, але це 19
U10-Вперед

5

Рекурсивні регулярні вирази можуть це зробити!

Настільки простий і зрозумілий алгоритм виявлення рядка, що містить паліндром:

   (\w)(?:(?R)|\w?)\1

На сайті rexegg.com/regex-recursion підручник пояснює, як це працює.


Він чудово працює з будь-якою мовою, ось приклад, адаптований з того ж джерела (посилання), що і доказ концепції, за допомогою PHP:

$subjects=['dont','o','oo','kook','book','paper','kayak','okonoko','aaaaa','bbbb'];
$pattern='/(\w)(?:(?R)|\w?)\1/';
foreach ($subjects as $sub) {
  echo $sub." ".str_repeat('-',15-strlen($sub))."-> ";
  if (preg_match($pattern,$sub,$m)) 
      echo $m[0].(($m[0]==$sub)? "! a palindrome!\n": "\n");
  else 
      echo "sorry, no match\n";
}

виходи

dont ------------> sorry, no match
o ---------------> sorry, no match
oo --------------> oo! a palindrome!
kook ------------> kook! a palindrome!
book ------------> oo
paper -----------> pap
kayak -----------> kayak! a palindrome!
okonoko ---------> okonoko! a palindrome!
aaaaa -----------> aaaaa! a palindrome!
bbbb ------------> bbb

Порівнюючи

Регулярний вираз ^((\w)(?:(?1)|\w?)\2)$ виконує ту саму роботу, але як так / не замість цього "містить".
PS: він використовує визначення, де "o" не є палімбромом, дефіс "sposob-elba" - це не паліндром, а "ableelba". Іменування його визначенням1 .
Коли "о" та "здатна ельба" є паліндронами, називаючи визначення2 .

Порівнюючи з іншими "регулярними виразами паліндрому",

  • ^((.)(?:(?1)|.?)\2)$базовий регулярний вираз вище без \wобмежень, приймаючи "здатний-ельбу".

  • ^((.)(?1)?\2|.)$( @LilDevil ) Використовуйте визначення2 (приймає "o" та "able-elba", що також відрізняється розпізнаванням рядків "aaaaa" та "bbbb").

  • ^((.)(?1)\2|.?)$ ( @Markus ) не виявлено ні "kook", ні "bbbb"

  • ^((.)(?1)*\2|.?)$( @Csaba ) Використовуйте визначення2 .


ПРИМІТКА: для порівняння ви можете додати більше слів $subjectsі рядок для кожного порівняного регулярного виразу,

  if (preg_match('/^((.)(?:(?1)|.?)\2)$/',$sub)) echo " ...reg_base($sub)!\n";
  if (preg_match('/^((.)(?1)?\2|.)$/',$sub)) echo " ...reg2($sub)!\n";
  if (preg_match('/^((.)(?1)\2|.?)$/',$sub)) echo " ...reg3($sub)!\n";
  if (preg_match('/^((.)(?1)*\2|.?)$/',$sub)) echo " ...reg4($sub)!\n";

5

Ви також можете зробити це без використання рекурсії:

\A(?:(.)(?=.*?((?(2)\1\2|\1))\z))*?.?\2\z

щоб дозволити один символ:

\A(?:(?:(.)(?=.*?((?(2)\1\2|\1))\z))*?.?\2|.)\z

Працює з Perl, PCRE

демо

Для Java:

\A(?:(.)(?=.*?(\1\2\z|(?<!(?=\2\z).{0,1000})\1\z)))*?.?\2\z

демо


1
Це дуже цікава відповідь на питання про регулярні вирази. Насправді єдиний зразок, який пройшов деякі мої тести . Дякую за це Казимиру :)
бульбашковий міхур

1
@bobblebubble: Дякуємо за вашу підтримку. Як бачите, я нещодавно відредагував цю відповідь, оскільки попередня версія була помилковою (три роки, яка ганьба).
Casimir et Hippolyte

4

Щодо виразу PCRE (від MizardX):

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

Ви перевіряли? На моєму PHP 5.3 під Win XP Pro він не працює: aaaba Насправді я дещо змінив вираз, щоб прочитати:

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

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

Цікаво, чи існує це виправлення, а також, чи правильно проходить мої тести приклад Perl (JF Sebastian / Zsolt)?

Чаба Габор з Відня




2

Як вказував ZCHudson , визначити, чи є щось паліндром, неможливо за допомогою звичайного регулярного виразу, оскільки набір паліндрому не є звичайною мовою.

Я абсолютно не згоден з Airsource Ltd, коли він каже, що "це неможливо" - це не той варіант відповіді, який шукає інтерв'юер. Під час свого інтерв’ю я приходжу до такого запитання, коли стикаюся з хорошим кандидатом, щоб перевірити, чи може він знайти правильний аргумент, коли ми запропонували йому зробити щось не так. Я не хочу наймати когось, хто спробує зробити щось не так, якщо він знає краще.



2

Я б пояснив інтерв'юеру, що мова, що складається з паліндромів, не є звичайною мовою, а натомість без контексту.

Регулярний вираз, який би відповідав усім паліндромам, був би нескінченним . Натомість я б запропонував йому обмежитися або максимальним розміром паліндромів, які слід прийняти; або якщо потрібні всі паліндроми, використовуйте як мінімум якийсь тип NDPA, або просто використовуйте просту техніку розвороту рядків / дорівнює.


2

Найкраще, що ви можете зробити із регулярними виразами, перш ніж вичерпаєте групи захоплення:

/(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?).?\9\8\7\6\5\4\3\2\1/

Це збігатиметься з усіма паліндромами довжиною до 19 символів.

Програматичне рішення для всіх довжин є тривіальним:

str == str.reverse ? true : false

Ваше регулярне вираження не працює. Наприклад, це вкаже, що "abac" - це збіг ...
Дарвін Айрола,

2

У мене ще немає представника для коментування, але регулярний вираз, наданий MizardX і модифікований Csaba, може бути змінений далі, щоб він працював у PCRE. Єдиною помилкою, яку я виявив, є рядок з одним символом, але я можу перевірити це окремо.

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

Якщо ви можете зробити так, щоб це не вдалося на будь-яких інших рядках, будь ласка, коментуйте.


2
#!/usr/bin/perl

use strict;
use warnings;

print "Enter your string: ";
chop(my $a = scalar(<STDIN>));    
my $m = (length($a)+1)/2;
if( (length($a) % 2 != 0 ) or length($a) > 1 ) { 
  my $r; 
  foreach (0 ..($m - 2)){
    $r .= "(.)";
  }
  $r .= ".?";
  foreach ( my $i = ($m-1); $i > 0; $i-- ) { 
    $r .= "\\$i";
  } 
  if ( $a =~ /(.)(.).\2\1/ ){
    print "$a is a palindrome\n";
  }
  else {
    print "$a not a palindrome\n";
 }
exit(1);
}
print "$a not a palindrome\n";

2

З теорії автоматів неможливо зіставити паліандром будь-якої довжини (оскільки для цього потрібен нескінченний обсяг пам'яті). Але МОЖЛИВО відповідати паліандромам фіксованої довжини. Скажімо, можна написати регулярний вираз, який відповідає всім паліандромам довжиною <= 5 або <= 6 тощо, але не> = 5 тощо, де верхня межа незрозуміла


2

У Ruby ви можете використовувати \b(?'word'(?'letter'[a-z])\g'word'\k'letter+0'|[a-z])\bдля збігу паліндромних слів, таких як a, dad, radar, racecar, and redivider. ps: цей регулярний вираз відповідає лише паліндромним словам із непарною кількістю літер.

Давайте подивимося, як цей регулярний вираз відповідає радару. Межа слова \ b збігається на початку рядка. Двигун регулярного виразу входить у групу захоплення "слово". [az] відповідає r, який потім зберігається у стеці для групи захоплення "буква" на рівні рекурсії нуль. Тепер механізм регулярних виразів вводить першу рекурсію групи "слово". (? 'буква' [az]) збігається і фіксує a на рівні рекурсії. Регулярний вираз вводить другу рекурсію групи "слово". (? 'буква' [az]) фіксує d на рівні рекурсії два. Під час наступних двох рекурсій група фіксує a та r на рівнях третій та четвертий. П’ята рекурсія не вдається, оскільки в рядку не залишилось символів, щоб [az] збігався. Двигун регулярних виразів повинен повернутися назад.

Тепер механізм регулярних виразів повинен спробувати другу альтернативу всередині групи "слово". Другий [az] у регулярному виразі відповідає кінцевому r у рядку. Тепер двигун виходить із успішної рекурсії, повертаючись на один рівень назад до третьої рекурсії.

Після зіставлення (& word) двигун досягає \ k'letter + 0 '. Зворотне посилання не вдається, оскільки механізм регулярного виразу вже досяг кінця рядка теми. Отож, він відтворюється ще раз. Друга альтернатива тепер відповідає a. Двигун регулярних виразів виходить із третьої рекурсії.

Двигун регулярних виразів знову збігається (& word) і повинен повторити спробу зворотного посилання. Зворотне посилання визначає +0 або поточний рівень рекурсії, який дорівнює 2. На цьому рівні група захоплення відповідає d. Зворотне посилання не вдається, оскільки наступним символом у рядку є r. Знову зворотне відстеження, другий альтернативний матч d.

Тепер \ k'letter + 0 'відповідає другому a у рядку. Це тому, що механізм регулярних виразів повернувся до першої рекурсії, під час якої група захоплення відповідала першій а. Двигун регулярних виразів виходить із першої рекурсії.

Двигун регулярних виразів повернувся поза всі рекурсії. Щоб цей рівень група захоплення зберігала r. Зворотне посилання тепер може відповідати кінцевому r у рядку. Оскільки двигун більше не знаходиться всередині жодної рекурсії, він продовжує роботу з рештою регулярних виразів після групи. \ b збіги в кінці рядка. Кінець регулярного виразу досягнуто, і радар повертається як загальний матч.


2

ось код PL / SQL, який повідомляє, чи є даний рядок паліндром чи не використовує регулярні вирази:

create or replace procedure palin_test(palin in varchar2) is
 tmp varchar2(100);
 i number := 0;
 BEGIN
 tmp := palin;
 for i in 1 .. length(palin)/2 loop
  if length(tmp) > 1 then  
    if regexp_like(tmp,'^(^.).*(\1)$') = true then 
      tmp := substr(palin,i+1,length(tmp)-2);
    else 
      dbms_output.put_line('not a palindrome');
      exit;
    end if;
  end if;  
  if i >= length(palin)/2 then 
   dbms_output.put_line('Yes ! it is a palindrome');
  end if;
 end loop;  
end palin_test;

2
my $pal='malayalam';

while($pal=~/((.)(.*)\2)/){                                 #checking palindrome word
    $pal=$3;
}
if ($pal=~/^.?$/i){                                         #matches single letter or no letter
    print"palindrome\n";
}
else{
    print"not palindrome\n";
}

2
Хоча цей код може відповісти на питання, надання додаткового контексту щодо того, як та / або чому він вирішує проблему, покращило б довгострокову цінність відповіді.
Дональд Дак,

2

Цей регулярний вираз виявлятиме паліндроми довжиною до 22 символів, ігноруючи пробіли, вкладки, коми та лапки.

\b(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*(?:(\w)[ \t,'"]*\11?[ \t,'"]*\10|\10?)[ \t,'"]*\9|\9?)[ \t,'"]*\8|\8?)[ \t,'"]*\7|\7?)[ \t,'"]*\6|\6?)[ \t,'"]*\5|\5?)[ \t,'"]*\4|\4?)[ \t,'"]*\3|\3?)[ \t,'"]*\2|\2?))?[ \t,'"]*\1\b

Пограйте з ним тут: https://regexr.com/4tmui


0

Невелике вдосконалення методу Airsource Ltd у псевдокоді:

WHILE string.length > 1
    IF /(.)(.*)\1/ matches string
        string = \2
    ELSE
        REJECT
ACCEPT
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.