Biểu thức chính quy đệ quy có thể làm được điều đó!
Thuật toán đơn giản và hiển nhiên để phát hiện một chuỗi có chứa palindrome:
(\w)(?:(?R)|\w?)\1
Tại rexegg.com/regex-recursion , hướng dẫn giải thích cách nó hoạt động.
Nó hoạt động tốt với bất kỳ ngôn ngữ nào, đây là một ví dụ được điều chỉnh từ cùng một nguồn (liên kết) làm bằng chứng khái niệm, sử dụng 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";
}
đầu ra
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
So sánh
Biểu thức chính quy ^((\w)(?:(?1)|\w?)\2)$
thực hiện công việc tương tự, nhưng thay vào đó là yes / not là "chứa".
Tái bút: nó đang sử dụng một định nghĩa trong đó "o" không phải là palimbrome, định dạng gạch nối "could-elba" không phải là palindrome, mà là "canelba". Đặt tên định nghĩa cho nó1 .
Khi "o" và "could-elba" là palindrones, định nghĩa đặt tên2 .
So sánh với một "palindrome regexes" khác,
^((.)(?:(?1)|.?)\2)$
base-regex ở trên mà không \w
bị hạn chế, chấp nhận "could-elba".
^((.)(?1)?\2|.)$
( @LilDevil ) Sử dụng định nghĩa2 (chấp nhận "o" và "could-elba", do đó cũng khác nhau trong việc nhận dạng các chuỗi "aaaaa" và "bbbb").
^((.)(?1)\2|.?)$
( @Markus ) không phát hiện thấy "kook" cũng như "bbbb"
^((.)(?1)*\2|.?)$
( @Csaba ) Sử dụng định nghĩa2 .
LƯU Ý: để so sánh, bạn có thể thêm nhiều từ hơn tại $subjects
và một dòng cho mỗi regex được so sánh,
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";