정규식을 사용하여 문자열이 회문인지 확인하는 방법은 무엇입니까?


93

제가 대답 할 수없는 인터뷰 질문이었습니다.

정규식을 사용하여 문자열이 회문인지 확인하는 방법은 무엇입니까?

추신 이미 " 주어진 문자열이 회문인지 확인하는 방법? "이라는 질문이 있으며 다른 언어로 많은 답변을 제공하지만 정규 표현식을 사용하는 답변은 없습니다.


1
stackoverflow.com/questions/3644266/… 아이디어를 줄 수 있습니다.
Prakhar

2
요즘 (2018)과 "회문 정규식"을 찾고있는 사람은 Prakhar의 링크에서 재귀 패턴 을 지원하는 PCRE에 대한 토론 과 비교와 함께 아래의 재귀 정규식을 참조하십시오 .
Peter Krauss

답변:


151

이 질문에 대한 대답은 "불가능하다"는 것입니다. 더 구체적으로 면접관은 당신이 계산 이론 수업에 관심을 기울 였는지 궁금해합니다.

계산 이론 수업에서 유한 상태 기계에 대해 배웠습니다. 유한 상태 머신은 노드와 에지로 구성됩니다. 각 모서리에는 유한 알파벳의 문자가 주석으로 표시됩니다. 하나 이상의 노드는 특수한 "수락"노드이고 한 노드는 "시작"노드입니다. 주어진 단어에서 각 문자를 읽을 때 우리는 기계의 주어진 가장자리를 횡단합니다. 수락 상태가되면 기계가 해당 단어를 "수락"한다고 말합니다.

정규식은 항상 동등한 유한 상태 기계로 변환 될 수 있습니다. 즉, 정규 표현식과 동일한 단어를 허용하고 거부하는 것입니다 (실제 세계에서 일부 정규 표현식 언어는 임의의 함수를 허용하지만 계산되지 않음).

모든 회문을 받아들이는 유한 상태 기계를 만드는 것은 불가능합니다. 증명은 임의로 많은 수의 노드가 필요한 문자열, 즉 문자열을 쉽게 만들 수 있다는 사실에 의존합니다.

a ^ xba ^ x (예 : aba, aabaa, aaabaaa, aaaabaaaa, ....)

여기서 a ^ x는 x 번 반복됩니다. 'b'를 본 후 회문인지 확인하기 위해 x 번 카운트해야하기 때문에 최소 x 개의 노드가 필요합니다.

마지막으로, 원래의 질문으로 돌아가서 면접관에게 유한 고정 길이보다 작은 모든 회문을 받아들이는 정규식을 작성할 수 있다고 말할 수 있습니다. 회문을 식별해야하는 실제 응용 프로그램이있는 경우 임의로 긴 응용 프로그램을 포함하지 않을 것이므로이 답변은 이론적 불가능 성을 실제 응용 프로그램과 구별 할 수 있음을 보여줍니다. 그래도 실제 정규 표현식은 동등한 4 줄 프로그램보다 훨씬 길다 (독자를위한 쉬운 연습 : 회문을 식별하는 프로그램 작성).


6
@SteveMoser Ruby 1.9.x에서 정규 표현식은 더 이상 정규 표현식이 아니므로 (Automata 이론의 의미에서) 회문 검사와 같은 일이 가능합니다. 그러나 의도와 목적을 위해 회문은 정규 정규식 으로 확인할 수 없습니다 (이해할 수 있습니까?).

1
@SteveMoser 여기에 Ruby의 정규식 엔진 ( >=1.9)에 대한 좋은 글이 있습니다

@John 맞습니다. 질문의 맥락에서 Jose가 맞고 hqt가 틀 렸습니다.
Steve Moser 2012

2
학문적 측면에서 정규 표현식에는 특정 경계가 있습니다 (DFA 정의). 실제로, 많은 정규 표현식 엔진 (Perl과 주로 친척)은 학문적 정의를 위반하는 역 참조를 지원합니다 (NFA 또는 그 이상이 됨). 그래서이 질문은 질문자의 기준 틀이 무엇이 었는지에 따라 다른 답을 가지고 있습니다.
jiggy

구두 테스트에서 zou shoulsd는 "formalz는 불가능합니다"로 이동하지만 일부 정규식 엔진이이를 허용한다는 점을 지적해야합니다.
올리버 A.

46

PCRE 엔진은 재귀 정규식을 지원 하지만 ( Peter Krauss의 답변 참조 ), 추가 코드없이이를 달성하기 위해 ICU 엔진 (예 : Apple 에서 사용)에서 정규식을 사용할 수 없습니다 . 다음과 같이해야합니다.

이것은 회문을 감지하지만 루프가 필요합니다 (정규 표현식이 계산할 수 없기 때문에 필요합니다).

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

4
좋은 대답입니다. 이 질문은 즉시 회문을 감지하는 단일 정규 표현식을 요구하지 않았습니다. 단순히 정규 표현식을 사용하는 회문을 감지하는 방법을 요청했습니다. 이런 식으로 보는 통찰력에 축하드립니다.
Stewart

1
하나의 정규식 만 사용하는 가장 간단한 매칭 (문자열 조작없이) 참조, stackoverflow.com/a/48608623/287948
Peter Krauss

@PeterKrauss 감사합니다. PCRE에 재귀가 있다는 것을 몰랐습니다. 귀하의 답변을 참조했습니다.
Airsource Ltd

32

불가능합니다. 회문은 일반 언어로 정의되지 않습니다. (참조, 나는 계산 이론에서 무언가를 배웠다)


2
대부분의 정규식 엔진은 정규 언어 이상을 캡처합니다 (예 : net은 일치하는 괄호를 캡처 할 수 있음). 표준 정규식 만 일반 언어로 제한됩니다.
Santiago Palladino

질문은 "정규식"이라는 용어를 사용했지만 ... 그래서 ZCHudson의 대답은 맞습니다.
paxos1977

2
@austirg : ZCHudson의 대답은 정확하지만 불완전합니다. 현대 프로그래밍 언어에서 사용되는 정규식과 이론적 CS 클래스에서 사용되는 정규식은 다른 짐승입니다. 이 용어는 단지 역사적인 유산입니다. stackoverflow.com/questions/233243#235199 및 내 대답을 참조하십시오 .
jfs

2
@JF Sebastian-나는 이것에 대해 austirg에 동의해야합니다. comp sci 정의가 적용되는 것보다 언급 된 특정 프로그래밍 언어없이 용어 정규식이 사용되는 경우. 정규 표현식을 지원하는 모든 언어가이 작업을 수행 할 수있는 것은 아니므로 여기에 사용 된 언어가이를 수행한다고 가정해서는 안됩니다.
Rontologist

@Rontologist : 질문에서 프로그래밍 언어 선택에 대한 제한이 없으므로 모든 언어가 허용됩니다. 오른쪽을보세요. 관련 질문에서 "정규 표현"의 의미는 무엇입니까? 특정 프로그래밍 언어가 언급되고 있습니까?
jfs

27

Perl 정규식 사용 :

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

많은 사람들이 지적했듯이 엄격하게하려면 정규 표현식으로 간주 할 수 없습니다. 정규식 은 재귀를 지원하지 않습니다.


이것은 PCRE에서 작동하지 않지만 ( "ababa"와 일치하지 않음) Perl 5.10에서 작동합니다
newacct

당신이 옳습니다. PCRE는 재귀를 원자 그룹으로 취급하는 것처럼 보이지만 Perl은 그 안에서 역 추적을 허용합니다. PCRE에서이 검사를 수행 할 수 없다고 생각합니다.
Markus Jarderot

1
놀랍게도 아르메니아어와 같은 비 라틴어에서는 작동하지 않습니다.
테무진

3
@Temujin 유니 코드 문자가 인코딩 된 바이트와 일치하기 때문 ( /umodifier 추가 ) 또는 결합 자 문자 때문입니다. (교체 .\X이스케이프 시퀀스 ).
Markus Jarderot 2016

1
내 패턴이 PCRE에서 작동하지 않습니다. Perl에서 작동합니다. 부분 문자열이 반복되면 패턴이 실패합니다. 예를 들면 abababa. PCRE 기반 정규식 엔진을 사용할 때 모든 입력에 대해 재귀로 작동하도록하는 것은 불가능합니다. Casimirs regex는 반복과 가변 상태를 사용하는 다른 접근 방식을 사용하며 매우 매력적입니다.
Markus Jarderot 19

15

다음 은 모든 유형의 캐릭터에 대해 4 글자 회문 (예 : deed)을 감지하는 것입니다.

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

다음 은 문자 만 확인하는 5 글자 회문 (예 : 레이더)을 감지하는 것입니다.

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

따라서 가능한 각 단어 길이에 대해 다른 정규식이 필요한 것 같습니다. Python 메일 링리스트 의이 게시물 에는 이유에 대한 세부 정보가 포함되어 있습니다 (Finite State Automata 및 pumping lemma).


14

당신이 얼마나 확신하는지에 따라이 대답을 드리겠습니다.

정규 표현식으로는하지 않을 것입니다. 정규 표현식의 적절한 사용이 아닙니다.


3
정규식의 한계를 정말로 이해하고 있음을 보여주기 위해 좀 더 설명을 해주셨 으면합니다. 귀하의 간단한 대답은 "난 당황스러워"라고 할 수 있습니다.
Scott Wegner

따라서 그가 준 의존 절.
Will Bickford

13

, .Net에서 할 수 있습니다!

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

여기에서 확인할 수 있습니다 ! 멋진 게시물입니다!


.NET 풍미 정규식의 요점은 유한 상태 자동 장치가 아니기 때문에 규칙적 이지 않다는 것입니다. 이론적 의미에서 실제로 정규식이 아닙니다.
cat

12

StackOverflow는 "정규식? 아니요, 지원하지 않습니다. 지원할 수 없습니다 ." 와 같은 답변으로 가득 차 있습니다 .

진실은 정규 표현식이 더 이상 정규 문법 과 관련이 없다는 것입니다. 현대의 정규 표현식은 재귀 및 균형 그룹과 같은 기능을 특징으로하며 그 구현의 가용성은 계속 증가하고 있습니다 (예를 들어 여기에서 Ruby 예제 참조). 제 생각에는 우리 분야의 정규식이 프로그래밍 개념이 아니라는 오래된 믿음에 매달리는 것은 단지 비생산적입니다. 더 이상 가장 적절하지 않은 단어 선택 때문에 그들을 미워하는 대신, 우리가 사물을 받아들이고 나아가 야 할 때입니다.

다음 은 Perl 자체를 만든 Larry Wall인용문입니다 .

(…) 일반적으로 실제 정규 표현식과 약간만 관련이있는 "정규 표현식"이라고 부르는 것과 관련이 있습니다. 그럼에도 불구하고이 용어는 패턴 매칭 엔진의 기능과 함께 성장 했으므로 여기서는 언어 적 필요성에 맞서 싸우지 않겠습니다. 그러나 저는 일반적으로 "정규식"(또는 앵글로색슨 분위기 일 때 "정규식")이라고 부를 것입니다.

다음 은 PHP의 핵심 개발자가 작성한 블로그 게시물 입니다 .

기사가 꽤 길었기 때문에 여기에 주요 요점을 요약했습니다.

  • 프로그래머가 사용하는 "정규식"은 형식 언어 이론의 맥락에서 원래의 정규성 개념과 거의 공통점이 없습니다.
  • 정규식 (최소 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


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
Steve Moser

2
당신이 올바른지. 이것이 내가 명명 된 캡처 그룹을 사용해야한다고 지적한 이유입니다.
테일러

누군가가 혹시 초보자를 위해 RE 캐릭터를 캐릭터별로 설명 할 수 있습니까? 다음은 모두 이해합니다 (쉼표로 '원자'구분) /, \ A, (, |, \ w, |, (, (, \ w,),),), \ z, /, x 이 중 어떤 것도 이해하지 못합니까? <p>,? :,? <l>, \ g <p>, \ k <l + 0> 그리고 도움을 위해 rubular.com을 사용하고 있으며 RE를 이해하는 것 같습니다 ( 당연히), 그러나 그것은 내가 그것을 보는 데 도움이되지 않으며 심지어 "완전한 Ruby 정규식 가이드는 Pickaxe를 참조하십시오." 왜냐하면 'Pickaxe'와 연결된 사이트는 내가 이해하지 못하는 원자를 설명하지 않기 때문입니다. 알아 ? 다음은 0 또는 a 중 하나와 일치하지만? 문자 앞에?
Kevin Ford the submariner

아, 명명 된 캡처 그룹 ! 좋은. @SteveMoser는 이제 끊어진 링크이지만 다른 . 언급 해주신 Taylor에게 감사합니다. 그렇지 않으면? <p>,? <l> 및? :( 캡처하지 않는 캡처 그룹) 및 \ g <p> 및 \ k <l +의 의미를 전혀 몰랐을 것입니다. 0>. 아직도 무엇을 볼 수 없습니까? <p> | 그래도. 하지 않습니다 | "또는"을 의미합니까? RE에서 파이프에 대한 사용법에 대한 문서를 찾을 수 없습니다. 이 아주 멋진 RE에 대한 자세한 설명을 보게되어 기쁩니다.
Kevin Ford the submariner

5

실제로 정규 표현식보다는 문자열 조작으로 수행하는 것이 더 쉽습니다.

bool isPalindrome(String s1)

{

    String s2 = s1.reverse;

    return s2 == s1;
}

나는 이것이 인터뷰 질문에 실제로 답하지 않는다는 것을 알고 있지만, 당신은 그것을 사용하여 당신이 작업을 수행하는 더 나은 방법을 어떻게 아는지를 보여줄 수 있습니다. 그리고 당신은 모든 문제를 못처럼 보는 전형적인 "망치를 가진 사람이 아닙니다." . "


이 답변을 아주 좋아하는 반면 BreakIterator를 사용하여 문자열을 시각적 문자로 적절하게 분할하면 추가 점수를 얻을 수 있다고 생각합니다.
Trejkaz 2014 년

5

Regex Golf의 5 단계 (A man, a plan)에 대한 제 답변 입니다. 브라우저의 정규식 (Chrome 36.0.1985.143을 사용하고 있음)으로 최대 7 자까지 작동합니다.

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

최대 9 자용입니다.

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

작동하는 최대 문자 수를 늘리려면 반복적으로 .? (:? () \ n..??)? .


1
약간 적은 문자로 관리했습니다. ^ (.) (.) (.)?.? \ 3 \ 2 \ 1 $
Ben Ellis

저에게 그것을 망쳐 주셔서 감사합니다 :-)
U10-Forward

왜 나머지 사람들은 13 명인데 이것은 19
U10-Forward

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)$ 은 동일한 작업을 수행하지만 "포함"대신 예 / 아니오로합니다.
추신 : "o"가 palimbrome이 아니라 "able-elba"하이픈 형식이 회문이 아닌 "ableelba"가있는 정의를 사용하고 있습니다. 이름 지정 definition1 .
"o"및 "able-elba"가 palindrone 인 경우 이름을 definition2로 지정 합니다 .

다른 "palindrome regexes"와 비교하면,

  • ^((.)(?:(?1)|.?)\2)$위의 기본 정규식은 \w제한 없이 "able-elba"를 허용합니다.

  • ^((.)(?1)?\2|.)$( @LilDevil ) definition2를 사용하십시오 ( "o"및 "able-elba"를 허용하므로 "aaaaa"및 "bbbb"문자열의 인식도 다릅니다).

  • ^((.)(?1)\2|.?)$( @Markus ) " kook "도 "bbbb"도 감지하지 못함

  • ^((.)(?1)*\2|.?)$( @Csaba ) definition2를 사용하십시오 .


참고 : 비교하기 위해 비교 된 $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
이것은 정규식 질문에 대한 매우 흥미로운 답변입니다. 실제로 일부 테스트통과 한 유일한 패턴 입니다. 이 하나를 주셔서 감사합니다 Casimir :)
bobble bubble

1
@bobblebubble : 지원해 주셔서 감사합니다. 보시다시피 이전 버전이 잘못 되었기 때문에 최근에이 답변을 편집했습니다 (3 년 동안, 얼마나 안타까운 일인지).
Casimir et Hippolyte

4

PCRE 식 (MizardX에서 제공) :

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

테스트 했습니까? Win XP Pro의 내 PHP 5.3에서는 다음과 같은 오류가 발생합니다. aaaba 실제로 식 표현식을 약간 수정하여 다음과 같이 읽습니다.

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

무슨 일이 일어나고 있는지는 외부 문자 쌍이 고정되어 있지만 나머지 내부 문자는 고정되어 있지 않다는 것입니다. 이것은 "aaaba"와 "aabaacaa"를 잘못 전달하지만 "aabaaca"에서는 제대로 실패하기 때문에 완전한 답이 아닙니다.

이에 대한 수정이 있는지 궁금합니다. 또한 Perl 예제 (JF Sebastian / Zsolt 작성)가 내 테스트를 올바르게 통과합니까?

비엔나에서 온 Csaba Gabor



3

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

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

오토마타 이론에서 어떤 길이의 팔리 안드로메와도 일치하는 것은 불가능합니다 (무한한 양의 메모리가 필요하기 때문입니다). 그러나 고정 길이의 Paliandromes와 일치하는 것이 가능합니다. 길이가 <= 5 또는 <= 6 등인 모든 팔리 안드로메와 일치하지만 상한이 불분명 한 경우> = 5 등이 아닌 정규식을 작성할 수 있다고 말합니다.


2

루비에서는 사용할 수있는 \b(?'word'(?'letter'[a-z])\g'word'\k'letter+0'|[a-z])\b등 회문 단어를 일치 a, dad, radar, racecar, and redivider. ps :이 정규식은 홀수의 문자 길이 인 회문 단어와 만 일치합니다.

이 정규식이 레이더와 어떻게 일치하는지 봅시다. 단어 경계 \ b는 문자열의 시작 부분과 일치합니다. 정규식 엔진이 캡처 그룹 "단어"에 들어갑니다. [az]는 재귀 수준 0에서 캡처 그룹 "문자"에 대한 스택에 저장되는 r과 일치합니다. 이제 정규식 엔진은 그룹 "단어"의 첫 번째 재귀를 입력합니다. (? 'letter'[az])는 재귀 수준 1과 일치하고 캡처합니다. 정규식은 그룹 "단어"의 두 번째 재귀를 입력합니다. (? 'letter'[az])는 재귀 수준 2에서 d를 캡처합니다. 다음 두 번의 재귀 동안 그룹은 레벨 3과 4에서 a와 r을 캡처합니다. 문자열에 [az] 일치 할 문자가 없기 때문에 다섯 번째 재귀가 실패합니다. 정규식 엔진은 역 추적해야합니다.

정규식 엔진은 이제 그룹 "단어"내에서 두 번째 대안을 시도해야합니다. 정규식의 두 번째 [az]는 문자열의 마지막 r과 일치합니다. 이제 엔진이 성공적인 재귀에서 빠져 나와 한 단계 뒤로 세 번째 재귀로 이동합니다.

일치 (& 단어) 후 엔진은 \ k'letter + 0 '에 도달합니다. 정규식 엔진이 이미 제목 문자열의 끝에 도달했기 때문에 역 참조가 실패합니다. 그래서 다시 한 번 역 추적합니다. 두 번째 대안은 이제 a와 일치합니다. 정규식 엔진은 세 번째 재귀에서 종료됩니다.

정규식 엔진이 다시 일치 (& word)되었으며 역 참조를 다시 시도해야합니다. 역 참조는 +0 또는 현재 재귀 수준 (2)을 지정합니다.이 수준에서 캡처 그룹은 d와 일치합니다. 문자열의 다음 문자가 r이기 때문에 역 참조가 실패합니다. 다시 역 추적하면 두 번째 대안이 d와 일치합니다.

이제 \ k'letter + 0 '은 문자열의 두 번째 a와 일치합니다. 이는 정규식 엔진이 캡처 그룹이 첫 번째 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
이 코드는 질문에 답할 수 있지만 문제를 해결하는 방법 및 / 또는 이유에 대한 추가 컨텍스트를 제공하면 답변의 장기적인 가치가 향상됩니다.
Donald Duck

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.