¡Las expresiones regulares recursivas pueden hacerlo!
Algoritmo tan simple y evidente para detectar una cadena que contiene un palíndromo:
(\w)(?:(?R)|\w?)\1
En rexegg.com/regex-recursion, el tutorial explica cómo funciona.
Funciona bien con cualquier idioma, aquí un ejemplo adaptado de la misma fuente (enlace) como prueba de concepto, usando 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";
}
salidas
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
Comparando
La expresión regular ^((\w)(?:(?1)|\w?)\2)$
hace el mismo trabajo, pero como sí / no "contiene".
PD: está usando una definición en la que "o" no es un palimbromo, el formato con guiones "able-elba" no es un palíndromo, pero "ableelba" sí lo es. Nombrarlo definición 1 .
Cuando "o" y "able-elba" son palindrones, nombrar definition2 .
En comparación con otras "expresiones regulares palindrómicas",
^((.)(?:(?1)|.?)\2)$
la base-regex anterior sin \w
restricción, aceptando "capaz-elba".
^((.)(?1)?\2|.)$
( @LilDevil ) Use definition2 (acepta "o" y "able-elba", por lo que también difieren en el reconocimiento de las cadenas "aaaaa" y "bbbb").
^((.)(?1)\2|.?)$
( @Markus ) no se detectó "kook" ni "bbbb"
^((.)(?1)*\2|.?)$
( @Csaba ) Utilice la definición 2 .
NOTA: para comparar, puede agregar más palabras en $subjects
y una línea para cada expresión regular comparada,
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";