นั่นเป็นคำถามสัมภาษณ์ที่ฉันไม่สามารถตอบได้:
จะตรวจสอบได้อย่างไรว่าสตริงเป็น palindrome โดยใช้นิพจน์ทั่วไป
ps มีคำถามอยู่แล้ว " จะตรวจสอบได้อย่างไรว่าสตริงที่ระบุเป็น palindrome หรือไม่ " และให้คำตอบมากมายในภาษาต่างๆ แต่ไม่มีคำตอบที่ใช้นิพจน์ทั่วไป
นั่นเป็นคำถามสัมภาษณ์ที่ฉันไม่สามารถตอบได้:
จะตรวจสอบได้อย่างไรว่าสตริงเป็น palindrome โดยใช้นิพจน์ทั่วไป
ps มีคำถามอยู่แล้ว " จะตรวจสอบได้อย่างไรว่าสตริงที่ระบุเป็น palindrome หรือไม่ " และให้คำตอบมากมายในภาษาต่างๆ แต่ไม่มีคำตอบที่ใช้นิพจน์ทั่วไป
คำตอบ:
คำตอบสำหรับคำถามนี้คือ "เป็นไปไม่ได้" โดยเฉพาะอย่างยิ่งผู้สัมภาษณ์สงสัยว่าคุณให้ความสนใจในชั้นเรียนทฤษฎีการคำนวณของคุณหรือไม่
ในชั้นเรียนทฤษฎีการคำนวณของคุณคุณได้เรียนรู้เกี่ยวกับเครื่องจักรที่มีสถานะ จำกัด เครื่องที่มีสถานะ จำกัด ประกอบด้วยโหนดและขอบ ขอบแต่ละด้านมีการใส่คำอธิบายประกอบด้วยตัวอักษรแบบ จำกัด โหนดอย่างน้อยหนึ่งโหนดเป็นโหนด "ยอมรับ" แบบพิเศษและหนึ่งโหนดคือโหนด "เริ่มต้น" เนื่องจากแต่ละตัวอักษรถูกอ่านจากคำที่กำหนดเราจึงข้ามขอบที่กำหนดในเครื่อง ถ้าเราอยู่ในสถานะยอมรับเราก็บอกว่าเครื่อง "ยอมรับ" คำนั้น
นิพจน์ทั่วไปสามารถแปลเป็นเครื่องสถานะ จำกัด ที่เทียบเท่าได้เสมอ นั่นคือคำที่ยอมรับและปฏิเสธคำเดียวกันกับนิพจน์ทั่วไป (ในโลกแห่งความเป็นจริงภาษา regexp บางภาษาอนุญาตให้ใช้ฟังก์ชันตามอำเภอใจซึ่งจะไม่นับรวม)
เป็นไปไม่ได้ที่จะสร้างเครื่องจักรที่มีสถานะ จำกัด ที่ยอมรับ palindromes ทั้งหมด การพิสูจน์ขึ้นอยู่กับข้อเท็จจริงที่ว่าเราสามารถสร้างสตริงที่ต้องการโหนดจำนวนมากโดยพลการนั่นคือสตริง
a ^ xba ^ x (เช่น aba, aabaa, aaabaaa, aaaabaaaa, .... )
โดยที่ ^ x คือ x คูณซ้ำ สิ่งนี้ต้องใช้อย่างน้อย x โหนดเพราะหลังจากเห็น 'b' เราต้องนับย้อน x คูณเพื่อให้แน่ใจว่าเป็นพาลินโดรม
ในที่สุดเมื่อกลับไปที่คำถามเดิมคุณสามารถบอกผู้สัมภาษณ์ได้ว่าคุณสามารถเขียนนิพจน์ทั่วไปที่ยอมรับ palindromes ทั้งหมดที่มีขนาดเล็กกว่าความยาวคงที่ จำกัด หากเคยมีแอปพลิเคชันในโลกแห่งความเป็นจริงที่ต้องระบุ palindromes ก็แทบจะไม่รวมถึงสิ่งที่ยาวตามอำเภอใจดังนั้นคำตอบนี้จะแสดงให้เห็นว่าคุณสามารถแยกความแตกต่างที่เป็นไปไม่ได้ทางทฤษฎีจากแอปพลิเคชันในโลกแห่งความเป็นจริง อย่างไรก็ตาม regexp ที่แท้จริงจะค่อนข้างยาวและยาวกว่าโปรแกรม 4 บรรทัดที่เทียบเท่ากันมาก (แบบฝึกหัดง่าย ๆ สำหรับผู้อ่าน: เขียนโปรแกรมที่ระบุ palindromes)
>=1.9
) ที่นี่
ในขณะที่เอ็นจิ้น PCREรองรับนิพจน์ทั่วไปแบบวนซ้ำ (ดูคำตอบของ Peter Krauss ) คุณไม่สามารถใช้ regex บนเอ็นจิ้น ICU (ตามที่ Apple ใช้เป็นต้น) เพื่อให้บรรลุสิ่งนี้โดยไม่ต้องใช้รหัสเพิ่มเติม คุณจะต้องทำสิ่งนี้:
สิ่งนี้ตรวจพบ palindrome ใด ๆ แต่ต้องมีการวนซ้ำ (ซึ่งจะต้องใช้เนื่องจากนิพจน์ทั่วไปไม่สามารถนับได้)
$a = "teststring";
while(length $a > 1)
{
$a =~ /(.)(.*)(.)/;
die "Not a palindrome: $a" unless $1 eq $3;
$a = $2;
}
print "Palindrome";
มันเป็นไปไม่ได้. Palindromes ไม่ได้กำหนดโดยภาษาปกติ (ดูฉันเรียนรู้บางอย่างในทฤษฎีการคำนวณ)
ด้วย Perl regex:
/^((.)(?1)\2|.?)$/
แม้ว่าจะมีหลายคนชี้ให้เห็นว่านี่ไม่สามารถถือเป็นนิพจน์ทั่วไปได้หากคุณต้องการเข้มงวด นิพจน์ทั่วไปไม่รองรับการเรียกซ้ำ
/u
ตัวปรับแต่ง ) หรือเนื่องจากอักขระ combinator (แทนที่.
ด้วย\X
ลำดับการหลีกเลี่ยง )
abababa
. เป็นไปไม่ได้ที่จะทำให้มันทำงานร่วมกับการเรียกซ้ำสำหรับทุกอินพุตเมื่อใช้เอนจิ้น regex บน PCRE Casimirs regex ใช้วิธีการที่แตกต่างกันโดยใช้การวนซ้ำและสถานะที่เปลี่ยนแปลงได้และค่อนข้างน่าสนใจ
ต่อไปนี้เป็นวิธีตรวจจับ palindromes 4 ตัวอักษร (เช่น: โฉนด) สำหรับอักขระประเภทใดก็ได้:
\(.\)\(.\)\2\1
นี่คือวิธีตรวจจับ palindromes 5 ตัวอักษร (เช่นเรดาร์) โดยตรวจหาตัวอักษรเท่านั้น:
\([a-z]\)\([a-z]\)[a-z]\2\1
ดูเหมือนว่าเราต้องการ regex ที่แตกต่างกันสำหรับความยาวของคำแต่ละคำ โพสต์นี้ในรายชื่อส่งเมล Python มีรายละเอียดบางอย่างเกี่ยวกับสาเหตุ (Finite State Automata และการปั๊มคำขยาย)
ขึ้นอยู่กับว่าคุณมั่นใจแค่ไหนฉันจะให้คำตอบนี้:
ฉันจะไม่ทำด้วยสีหน้าปกติ ไม่ใช่การใช้นิพจน์ทั่วไปที่เหมาะสม
StackOverflow เต็มไปด้วยคำตอบเช่น "นิพจน์ทั่วไปหรือไม่ไม่รองรับไม่รองรับ"
ความจริงก็คือนิพจน์ทั่วไปไม่มีอะไรเกี่ยวข้องกับไวยากรณ์ปกติอีกต่อไป ฟังก์ชันคุณลักษณะของนิพจน์ทั่วไปที่ทันสมัยเช่นการเรียกซ้ำและการปรับสมดุลกลุ่มและความพร้อมใช้งานของการนำไปใช้นั้นเพิ่มขึ้นเรื่อย ๆ (ดูตัวอย่าง Ruby ที่นี่เป็นต้น) ในความคิดของฉันการยึดติดกับความเชื่อเดิม ๆ ว่านิพจน์ทั่วไปในสาขาของเราเป็นอะไรก็ได้ แต่แนวคิดการเขียนโปรแกรมเป็นเพียงการต่อต้าน แทนที่จะเกลียดพวกเขาสำหรับคำว่าทางเลือกที่ไม่เหมาะสมที่สุดอีกต่อไปถึงเวลาแล้วที่เราต้องยอมรับสิ่งต่างๆและก้าวต่อไป
นี่คือคำพูดจาก Larry Wallผู้สร้าง Perl เอง:
(…) โดยทั่วไปจะเกี่ยวข้องกับสิ่งที่เราเรียกว่า "นิพจน์ทั่วไป" ซึ่งเกี่ยวข้องกับนิพจน์ทั่วไปจริงเพียงเล็กน้อยเท่านั้น อย่างไรก็ตามคำนี้เติบโตขึ้นพร้อมกับความสามารถของเครื่องมือจับคู่รูปแบบของเราดังนั้นฉันจะไม่พยายามต่อสู้กับความจำเป็นทางภาษาที่นี่ อย่างไรก็ตามโดยทั่วไปฉันจะเรียกพวกเขาว่า "regexes" (หรือ "regexen" เมื่อฉันอยู่ในอารมณ์แองโกล - แซกซอน)
และนี่คือบล็อกโพสต์โดยหนึ่งในนักพัฒนาหลักของ PHP :
เนื่องจากบทความค่อนข้างยาวจึงสรุปประเด็นหลักดังนี้
- "นิพจน์ทั่วไป" ที่โปรแกรมเมอร์ใช้มีความเหมือนกันน้อยมากกับแนวคิดดั้งเดิมของความสม่ำเสมอในบริบทของทฤษฎีภาษาที่เป็นทางการ
- นิพจน์ทั่วไป (อย่างน้อย PCRE) สามารถจับคู่ภาษาที่ไม่มีบริบทได้ทั้งหมด ด้วยเหตุนี้จึงสามารถจับคู่ HTML ที่มีรูปแบบดีและภาษาโปรแกรมอื่น ๆ ได้ทั้งหมด
- นิพจน์ทั่วไปสามารถจับคู่ภาษาที่คำนึงถึงบริบทได้เป็นอย่างน้อย
- การจับคู่นิพจน์ทั่วไปเป็นแบบ NP-complete ดังนั้นคุณสามารถแก้ปัญหา NP อื่น ๆ โดยใช้นิพจน์ทั่วไป
ดังที่กล่าวไว้คุณสามารถจับคู่ palindromes กับ regexes ได้โดยใช้สิ่งนี้:
^(?'letter'[a-z])+[a-z]?(?:\k'letter'(?'-letter'))+(?(letter)(?!))$
... ซึ่งเห็นได้ชัดว่าไม่มีอะไรเกี่ยวข้องกับไวยากรณ์ปกติ
ข้อมูลเพิ่มเติมที่นี่: http://www.regular-expressions.info/balancing.html
ดังที่ได้กล่าวไปแล้วไม่มี regexp เดียวที่จะตรวจจับ palindrome ทั่วไปออกจากกล่อง แต่ถ้าคุณต้องการตรวจจับ palindromes ที่มีความยาวสูงสุดคุณสามารถใช้สิ่งต่างๆเช่น
(.?)(.?)(.?)(.?)(.?).?\5\4\3\2\1
สามารถทำได้ใน Perl ตอนนี้ ใช้การอ้างอิงแบบเรียกซ้ำ:
if($istr =~ /^((\w)(?1)\g{-1}|\w?)$/){
print $istr," is palindrome\n";
}
แก้ไขตามส่วนสุดท้ายที่อยู่ใกล้http://perldoc.perl.org/perlretut.html
ในทับทิมคุณสามารถใช้กลุ่มการจับภาพที่มีชื่อ ดังนั้นสิ่งนี้จะได้ผล -
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
มันง่ายกว่าที่จะทำด้วยการจัดการสตริงมากกว่านิพจน์ทั่วไป:
bool isPalindrome(String s1)
{
String s2 = s1.reverse;
return s2 == s1;
}
ฉันตระหนักดีว่านี่ไม่ได้ตอบคำถามสัมภาษณ์จริงๆ แต่คุณสามารถใช้เพื่อแสดงให้เห็นว่าคุณรู้วิธีการทำงานที่ดีขึ้นได้อย่างไรและคุณไม่ใช่ "คนทั่วไปที่ถือค้อนซึ่งมองทุกปัญหาเป็นเหมือนเล็บ .”
นี่คือคำตอบของฉันสำหรับระดับที่ 5 ของ Regex Golf (ชายคนหนึ่งแผน) ใช้งานได้สูงสุด 7 ตัวอักษรด้วย Regexp ของเบราว์เซอร์ (ฉันใช้ Chrome 36.0.1985.143)
^(.)(.)(?:(.).?\3?)?\2\1$
นี่คือหนึ่งสำหรับอักขระไม่เกิน 9 ตัว
^(.)(.)(?:(.)(?:(.).?\4?)?\3?)?\2\1$
หากต้องการเพิ่มจำนวนอักขระสูงสุดที่ใช้ได้คุณจะแทนที่ซ้ำ ๆ? กับ(?: (.).? \ n?)? .
อัลกอริธึมที่เรียบง่ายและชัดเจนในการตรวจจับสตริงที่มี palindrome:
(\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" ไม่ใช่ palindrome แต่เป็น "canelba" การตั้งชื่อนิยาม 1.
เมื่อ "o" และ "able-elba" เป็น palindrones การตั้งชื่อdefinition2 .
เมื่อเปรียบเทียบกับ "palindrome regexes" อื่น
^((.)(?:(?1)|.?)\2)$
base-regex ด้านบนโดยไม่มี\w
ข้อ จำกัด ยอมรับ "able-elba"
^((.)(?1)?\2|.)$
( @LilDevil ) ใช้คำจำกัดความ 2 (ยอมรับ "o" และ "able-elba" ซึ่งแตกต่างกันในการรับรู้สตริง "aaaaa" และ "bbbb")
^((.)(?1)\2|.?)$
( @Markus ) ตรวจไม่พบ "kook" หรือ "bbbb"
^((.)(?1)*\2|.?)$
( @Csaba ) ใช้คำจำกัดความ 2.
หมายเหตุ: ในการเปรียบเทียบคุณสามารถเพิ่มคำเพิ่มเติมที่$subjects
และบรรทัดสำหรับ regex ที่เปรียบเทียบแต่ละรายการ
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";
^((.)(?:(?1)|.?)\2|(.)\3*)$
เกี่ยวกับนิพจน์ PCRE (จาก MizardX):
/^((.)(?1)\2|.?)$/
คุณได้ทดสอบหรือไม่? บน PHP 5.3 ของฉันภายใต้ Win XP Pro มันล้มเหลวบน: aaaba จริงๆแล้วฉันแก้ไขนิพจน์นิพจน์เล็กน้อยเพื่ออ่าน:
/^((.)(?1)*\2|.?)$/
ฉันคิดว่าสิ่งที่เกิดขึ้นคือในขณะที่ตัวละครคู่นอกถูกยึดไว้ แต่ตัวละครชั้นในที่เหลือไม่ได้ นี่ไม่ใช่คำตอบทั้งหมดเพราะในขณะที่ส่งผ่าน "aaaba" และ "aabaacaa" อย่างไม่ถูกต้อง แต่ก็ไม่ถูกต้องใน "aabaaca"
ฉันสงสัยว่ามีการแก้ไขสำหรับสิ่งนี้หรือไม่และตัวอย่าง Perl (โดย JF Sebastian / Zsolt) ผ่านการทดสอบของฉันอย่างถูกต้องหรือไม่
Csaba Gabor จากเวียนนา
/\A(?<a>|.|(?:(?<b>.)\g<a>\k<b+0>))\z/
ใช้ได้กับเครื่องยนต์ Oniguruma (ซึ่งใช้ใน Ruby)
เอามาจากPragmatic Bookshelf
ใน 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
}
regex นี้จะตรวจจับ palindromes สูงสุด 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
ตามที่ZCHudsonชี้ไว้ให้ตรวจสอบว่าบางสิ่งที่เป็น palindrome ไม่สามารถทำได้ด้วย regexp ตามปกติเนื่องจากชุดของ palindrome ไม่ใช่ภาษาปกติ
ฉันไม่เห็นด้วยกับAirsource Ltdอย่างสิ้นเชิง เมื่อเขาบอกว่า "มันเป็นไปไม่ได้" ไม่ใช่คำตอบที่ผู้สัมภาษณ์ต้องการ ในระหว่างการสัมภาษณ์ของฉันฉันเจอคำถามแบบนี้เมื่อฉันเผชิญหน้ากับผู้สมัครที่ดีเพื่อตรวจสอบว่าเขาสามารถหาข้อโต้แย้งที่ถูกต้องได้หรือไม่เมื่อเราเสนอให้เขาทำอะไรผิด ฉันไม่อยากจ้างคนที่พยายามทำอะไรผิด ๆ ถ้าเขารู้ดีกว่านี้
สิ่งที่คุณสามารถทำได้ด้วย perl: http://www.perlmonks.org/?node_id=577368
ฉันจะอธิบายให้ผู้สัมภาษณ์เข้าใจว่าภาษาที่ประกอบด้วยภาษาปาลินโดรมไม่ใช่ภาษาปกติ แต่ไม่มีบริบทแทน
การแสดงออกปกติที่จะตรงกับ palindromes ทั้งหมดจะไม่มีที่สิ้นสุด แต่ฉันขอแนะนำให้เขา จำกัด ตัวเองให้มีขนาดสูงสุดของ palindromes ที่จะยอมรับได้ หรือถ้าจำเป็นต้องใช้ palindromes ทั้งหมดให้ใช้ NDPA บางประเภทอย่างน้อยที่สุดหรือใช้เทคนิคการกลับตัว / เท่ากับสตริงอย่างง่าย
สิ่งที่ดีที่สุดที่คุณสามารถทำได้กับ regexes ก่อนที่คุณจะหมดกลุ่มการบันทึก:
/(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?)(.?).?\9\8\7\6\5\4\3\2\1/
สิ่งนี้จะจับคู่ palindromes ทั้งหมดที่มีความยาวไม่เกิน 19 อักขระ
การแก้โปรแกรมสำหรับความยาวทั้งหมดเป็นเรื่องเล็กน้อย:
str == str.reverse ? true : false
ฉันยังไม่มีตัวแทนที่จะแสดงความคิดเห็นแบบอินไลน์ แต่ regex ที่ MizardX จัดหาให้และแก้ไขโดย Csaba สามารถแก้ไขเพิ่มเติมเพื่อให้ทำงานใน PCRE ได้ ความล้มเหลวเพียงอย่างเดียวที่ฉันพบคือสตริงอักขระเดี่ยว แต่ฉันสามารถทดสอบแยกกันได้
/^((.)(?1)?\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";
จากทฤษฎีออโตมาตามันเป็นไปไม่ได้ที่จะจับคู่กับความยาวใด ๆ (เนื่องจากต้องใช้หน่วยความจำจำนวนไม่ จำกัด ) แต่มันเป็นไปได้ที่จะจับคู่ภาษาบาลีของความยาวคงที่ บอกว่าเป็นไปได้ที่จะเขียนนิพจน์ทั่วไปที่ตรงกับความยาวภาษาบาลีทั้งหมด <= 5 หรือ <= 6 ฯลฯ แต่ไม่ใช่> = 5 เป็นต้นโดยที่ขอบเขตบนไม่ชัดเจน
ใน Ruby คุณสามารถใช้\b(?'word'(?'letter'[a-z])\g'word'\k'letter+0'|[a-z])\b
เพื่อจับคู่คำของ palindrome เช่นa, dad, radar, racecar, and redivider
. ps: regex นี้จับคู่เฉพาะคำ palindrome ที่มีตัวอักษรยาวเป็นจำนวนคี่
มาดูกันว่า regex นี้จับคู่กับเรดาร์ได้อย่างไร คำว่า bound \ b ตรงกับจุดเริ่มต้นของสตริง เอ็นจิ้น regex เข้าสู่กลุ่มการจับ "word" [az] จับคู่ r ซึ่งจะถูกเก็บไว้ในสแต็กสำหรับกลุ่มการจับภาพ "letter" ที่ระดับการเรียกซ้ำศูนย์ ตอนนี้เอ็นจิ้น regex เข้าสู่การเรียกซ้ำครั้งแรกของกลุ่ม "word" (? 'letter' [az]) จับคู่และบันทึกในระดับการเรียกซ้ำหนึ่ง regex เข้าสู่การเรียกซ้ำครั้งที่สองของกลุ่ม "word" (? 'letter' [az]) จับ d ที่ระดับการเรียกซ้ำสอง ในระหว่างการเรียกซ้ำสองครั้งถัดไปกลุ่มจะจับ a และ r ที่ระดับสามและสี่ การเรียกซ้ำครั้งที่ห้าล้มเหลวเนื่องจากไม่มีอักขระเหลืออยู่ในสตริงให้ [az] จับคู่ เอนจิ้น regex ต้องย้อนรอย
ตอนนี้เอ็นจิ้น regex ต้องลองใช้ทางเลือกที่สองในกลุ่ม "word" [az] ตัวที่สองใน regex ตรงกับ r สุดท้ายในสตริง ขณะนี้เครื่องยนต์ออกจากการเรียกซ้ำที่ประสบความสำเร็จแล้วโดยจะสำรองหนึ่งระดับไปยังการเรียกซ้ำครั้งที่สาม
หลังจากจับคู่ (& word) เครื่องยนต์จะถึง \ k'letter + 0 ' การอ้างอิงกลับล้มเหลวเนื่องจากเอ็นจิ้น regex ได้มาถึงจุดสิ้นสุดของสตริงหัวเรื่องแล้ว ดังนั้นจึงย้อนรอยอีกครั้ง ทางเลือกที่สองตอนนี้ตรงกับไฟล์. เอ็นจิ้น regex ออกจากการเรียกซ้ำครั้งที่สาม
เอ็นจิ้น regex ได้จับคู่ (& word) อีกครั้งแล้วและจำเป็นต้องพยายามย้อนกลับอีกครั้ง backreference ระบุ +0 หรือระดับปัจจุบันของการเรียกซ้ำซึ่งก็คือ 2 ในระดับนี้กลุ่มการจับจับคู่ d backreference ล้มเหลวเนื่องจากอักขระถัดไปในสตริงคือ r ย้อนกลับอีกครั้งทางเลือกที่สองตรงกับ d.
ตอนนี้ \ k'letter + 0 'จะจับคู่ a ตัวที่สองในสตริง นั่นเป็นเพราะเอ็นจิ้น regex กลับมาถึงการเรียกซ้ำครั้งแรกในระหว่างที่กลุ่มการจับจับคู่กับ a. เอ็นจิ้น regex ออกจากการเรียกซ้ำครั้งแรก
ขณะนี้เอ็นจิ้น regex กลับมาอยู่นอกการเรียกซ้ำทั้งหมดแล้ว ระดับนี้กลุ่มการจับเก็บไว้ r. backreference สามารถจับคู่ r สุดท้ายในสตริงได้แล้ว เนื่องจากเครื่องยนต์ไม่ได้อยู่ในการเรียกซ้ำอีกต่อไปมันจะดำเนินการกับส่วนที่เหลือของ regex หลังจากกลุ่ม \ b จับคู่ที่ส่วนท้ายของสตริง ถึงจุดสิ้นสุดของ regex และเรดาร์จะกลับมาเหมือนการจับคู่โดยรวม
นี่คือรหัส PL / SQL ซึ่งจะบอกว่าสตริงที่กำหนดเป็น palindrome หรือไม่ใช้นิพจน์ทั่วไป:
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;
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";
}
การปรับแต่งวิธีการของ Airsource Ltd เล็กน้อยในรหัสเทียม:
WHILE string.length > 1
IF /(.)(.*)\1/ matches string
string = \2
ELSE
REJECT
ACCEPT