Come verificare che una stringa sia un palindromo usando espressioni regolari?


93

Quella era una domanda dell'intervista a cui non sono stato in grado di rispondere:

Come verificare che una stringa sia un palindromo usando espressioni regolari?

ps C'è già una domanda " Come verificare se la stringa data è palindromo? " e fornisce molte risposte in diverse lingue, ma nessuna risposta che utilizza espressioni regolari.



2
Per i giorni nostri (2018) e chi è alla ricerca della "regex palindromo", vedere la discussione su PCRE che supporta pattern ricorsivi al collegamento di Prakhar e la mia regex ricorsiva di seguito, con i confronti .
Peter Krauss

Risposte:


151

La risposta a questa domanda è che "è impossibile". Più specificamente, l'intervistatore si chiede se hai prestato attenzione nella tua lezione di teoria computazionale.

Nella tua lezione di teoria computazionale hai imparato a conoscere le macchine a stati finiti. Una macchina a stati finiti è composta da nodi e archi. Ogni bordo è annotato con una lettera di un alfabeto finito. Uno o più nodi sono nodi speciali "di accettazione" e un nodo è il nodo "iniziale". Quando ogni lettera viene letta da una data parola, attraversiamo il bordo dato nella macchina. Se finiamo in uno stato di accettazione, allora diciamo che la macchina "accetta" quella parola.

Un'espressione regolare può sempre essere tradotta in una macchina a stati finiti equivalente. Cioè, uno che accetta e rifiuta le stesse parole dell'espressione regolare (nel mondo reale, alcuni linguaggi regexp consentono funzioni arbitrarie, queste non contano).

È impossibile costruire una macchina a stati finiti che accetti tutti i palindromi. La dimostrazione si basa sul fatto che possiamo facilmente costruire una stringa che richiede un numero arbitrariamente grande di nodi, vale a dire la stringa

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

dove a ^ x è una ripetuta x volte. Ciò richiede almeno x nodi perché, dopo aver visto la "b", dobbiamo contare x volte per assicurarci che sia un palindromo.

Infine, tornando alla domanda iniziale, potresti dire all'intervistatore che puoi scrivere un'espressione regolare che accetti tutti i palindromi che sono più piccoli di una lunghezza fissa finita. Se c'è mai un'applicazione del mondo reale che richiede l'identificazione dei palindromi, quasi certamente non includerà quelli arbitrariamente lunghi, quindi questa risposta mostrerebbe che è possibile differenziare le impossibilità teoriche dalle applicazioni del mondo reale. Tuttavia, la regexp effettiva sarebbe piuttosto lunga, molto più lunga di un equivalente programma di 4 righe (esercizio facile per il lettore: scrivere un programma che identifichi i palindromi).


6
@SteveMoser In Ruby 1.9.x, le espressioni regolari non sono più regolari (nel senso della teoria degli automi) e quindi sono possibili cose come il controllo dei palindromi. Tuttavia, per gli intenti e gli scopi, i palindromi non possono essere controllati con un'espressione regolare regolare (ha senso?).

1
@SteveMoser C'è una buona descrizione del motore delle espressioni regolari di Ruby ( >=1.9) qui

@ John ha ragione, quindi nel contesto della domanda Jose ha ragione e hqt è sbagliato.
Steve Moser

2
In termini accademici, un'espressione regolare ha limiti specifici (definisce un DFA). In realtà, molti motori di regexp (Perl ed i suoi parenti principalmente) supportano backreferences che violano la definizione accademica (diventando NFA o anche più ampi). Quindi questa domanda ha risposte diverse a seconda di quale fosse il quadro di riferimento dell'interrogante.
jiggy

In una prova orale dovresti dire "formalz è impossibile", ma dovresti sottolineare che alcuni motori di regex lo consentono.
Oliver A.

46

Sebbene il motore PCRE supporti le espressioni regolari ricorsive (vedere la risposta di Peter Krauss ), non è possibile utilizzare un'espressione regolare sul motore ICU (come utilizzato, ad esempio, da Apple) per ottenere ciò senza codice aggiuntivo. Avrai bisogno di fare qualcosa del genere:

Questo rileva qualsiasi palindromo, ma richiede un ciclo (che sarà richiesto perché le espressioni regolari non possono contare).

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

4
Buona risposta. La domanda non chiedeva una singola espressione regolare che rilevi un palindromo direttamente dalla scatola, ma semplicemente un metodo per rilevare i palindromi che utilizza le espressioni regolari. Congratulazioni per la tua intuizione di vederla in questo modo.
Stewart

1
Vedi anche la corrispondenza più semplice (senza manipolazione delle stringhe) usando solo una regex, stackoverflow.com/a/48608623/287948
Peter Krauss

Grazie @PeterKrauss. Non sapevo che PCRE avesse la ricorsione. Riferimento alla tua risposta.
Airsource Ltd

32

Non è possibile. I palindromi non sono definiti da un linguaggio normale. (Vedi, ho imparato qualcosa nella teoria computazionale)


2
La maggior parte dei motori di espressioni regolari acquisisce più dei linguaggi normali (net può catturare le parentesi corrispondenti per esempio). Solo le espressioni regolari standard sono limitate alle lingue regolari.
Santiago Palladino

La domanda utilizzava il termine "espressione regolare" però ... quindi la risposta di ZCHudson è corretta.
paxos1977

2
@austirg: la risposta di ZCHudson è corretta ma incompleta. Le espressioni regolari utilizzate nei linguaggi di programmazione moderni e le espressioni regolari utilizzate nelle classi teoriche CS sono bestie diverse. Il termine è solo un patrimonio storico. Vedi stackoverflow.com/questions/233243#235199 e la mia risposta.
jfs

2
@ JF Sebastian - Dovrei essere d'accordo con austirg su questo. Quando il termine espressione regolare viene utilizzato senza menzionare un linguaggio di programmazione specifico, si applica la definizione di comp sci. Non tutti i linguaggi che supportano le espressioni regolari possono farlo, quindi non dovremmo presumere che quello usato qui lo faccia.
Rontologo

@Rontologist: non vedo restrizioni sulla scelta del linguaggio di programmazione nella domanda, quindi è consentita qualsiasi lingua. Guarda a destra: qual è il significato di "espressione regolare" nelle relative domande? In qualcuno di essi viene menzionato un linguaggio di programmazione specifico?
jfs

27

Con regex Perl:

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

Tuttavia, come molti hanno sottolineato, questa non può essere considerata un'espressione regolare se vuoi essere rigoroso. Le espressioni regolari non supportano la ricorsione.


questo non funziona in PCRE (non corrisponde ad "ababa"), ma funziona in Perl 5.10
newacct

Hai ragione. PCRE sembra trattare la ricorsione come un gruppo atomico, mentre Perl consente il backtracking al suo interno. Non credo sia possibile fare questo controllo in PCRE.
Markus Jarderot

1
Sorprendentemente, non funziona per le lingue non latine, ad esempio la lingua armena.
Temujin

3
@Temujin È o perché i caratteri Unicode vengono abbinati come byte codificati (aggiungi il /umodificatore ) o perché i caratteri combinatori. (sostituire .con la \Xsequenza di escape ).
Markus Jarderot

1
Il mio modello non funziona in PCRE. Funziona in Perl. Il tuo modello fallisce quando vengono ripetute sottostringhe. Ad esempio abababa. Non è possibile farlo funzionare con la ricorsione per ogni input quando si utilizzano motori regex basati su PCRE. La regex di Casimirs utilizza un approccio diverso, utilizzando l'iterazione e lo stato mutabile, ed è piuttosto affascinante.
Markus Jarderot

15

Eccone uno per rilevare palindromi di 4 lettere (ad esempio: atto), per qualsiasi tipo di carattere:

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

Eccone uno per rilevare palindromi a 5 lettere (ad esempio: radar), controllando solo le lettere:

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

Quindi sembra che abbiamo bisogno di una regex diversa per ogni possibile lunghezza di parola. Questo post su una mailing list Python include alcuni dettagli sul perché (Finite State Automata e pumping lemma).


14

A seconda di quanto sei sicuro, darei questa risposta:

Non lo farei con un'espressione regolare. Non è un uso appropriato delle espressioni regolari.


3
Spero che tu fornisca qualche spiegazione in più, per dimostrare che capisci davvero i limiti delle espressioni regolari. La tua semplice risposta potrebbe essere interpretata come "Sono perplesso".
Scott Wegner

Da qui la clausola di dipendenza che ha dato.
Will Bickford

13

, puoi farlo in .Net!

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

Puoi verificarlo qui ! È un post meraviglioso!


L'intero punto di Regex aromatizzato con .NET è che non sono regolari perché non sono un automa a stati finiti; non sono realmente regex in senso teorico.
gatto

12

StackOverflow è pieno di risposte come "Espressioni regolari? No, non lo supportano. Non possono supportarlo.".

La verità è che le espressioni regolari non hanno più nulla a che fare con le grammatiche regolari . Le espressioni regolari moderne dispongono di funzioni come la ricorsione e il bilanciamento dei gruppi e la disponibilità delle loro implementazioni è in continua crescita (vedi esempi di Ruby qui, per esempio). A mio parere, aggrapparsi alla vecchia convinzione che le espressioni regolari nel nostro campo siano tutt'altro che un concetto di programmazione è semplicemente controproducente. Invece di odiarli per la parola scelta che non è più la più appropriata, è tempo per noi di accettare le cose e andare avanti.

Ecco una citazione di Larry Wall , il creatore di Perl stesso:

(…) Generalmente hanno a che fare con quelle che chiamiamo "espressioni regolari", che sono solo marginalmente correlate alle espressioni regolari reali. Tuttavia, il termine è cresciuto con le capacità dei nostri motori di pattern matching, quindi non cercherò di combattere la necessità linguistica qui. Tuttavia, le chiamerò generalmente "regex" (o "regexen", quando sono di umore anglosassone).

Ed ecco un post sul blog di uno degli sviluppatori principali di PHP :

Dato che l'articolo era piuttosto lungo, ecco un riassunto dei punti principali:

  • Le "espressioni regolari" usate dai programmatori hanno molto poco in comune con la nozione originale di regolarità nel contesto della teoria del linguaggio formale.
  • Le espressioni regolari (almeno PCRE) possono corrispondere a tutti i linguaggi privi di contesto. In quanto tali, possono anche abbinare HTML ben formato e praticamente tutti gli altri linguaggi di programmazione.
  • Le espressioni regolari possono corrispondere almeno ad alcuni linguaggi sensibili al contesto.
  • La corrispondenza delle espressioni regolari è NP-completa. In quanto tale, puoi risolvere qualsiasi altro problema NP utilizzando espressioni regolari.

Detto questo, puoi abbinare palindromi con regex usando questo:

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

... che ovviamente non ha nulla a che fare con le grammatiche regolari.
Maggiori informazioni qui: http://www.regular-expressions.info/balancing.html


9

Come alcuni hanno già detto, non esiste una singola espressione regolare che rileverà un palindromo generale fuori dagli schemi, ma se vuoi rilevare palindromi fino a una certa lunghezza, puoi usare qualcosa di simile

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


6

In ruby ​​puoi usare gruppi di cattura con nome. quindi qualcosa del genere funzionerà -

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

provalo, funziona ...

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

1
I gruppi di cattura con nome non sono strettamente regex. willamette.edu/~fruehr/LLC/lab5.html
Steve Moser,

2
Hai ragione. Questo è in particolare il motivo per cui ho sottolineato che dovresti usare gruppi di cattura con nome.
Taylor

Qualcuno potrebbe per caso spiegare quell'IR carattere per carattere per un principiante? Capisco tutto quanto segue (le virgole separano gli "atomi") /, \ A, (, |, \ w, |, (, (, \ w,),),), \ z, /, x ma non non capisci nessuno di questi? <p>,?:,? <l>, \ g <p>, \ k <l + 0> e sto usando rubular.com per aiuto e sembra capire il RE ( naturalmente), ma questo non mi aiuta a vederlo, e anche "Per una guida completa alle espressioni regolari di Ruby, vedi Piccone". non aiuta, perché il sito collegato con "Pickaxe" non spiega gli atomi che non riesco a capire. Lo so ? SEGUENDO una corrispondenza di Zero o una di una, ma? che precede un personaggio?
Kevin Ford il sottomarino

Ah, gruppi di cattura denominati ! Bello. @SteveMoser che ora è un collegamento interrotto, ma ne ho trovato un altro . Grazie Taylor per averli menzionati, altrimenti non avrei avuto idea di cosa si intendesse per? <p> e? <l> e?: (Gruppo di cattura non di cattura) e \ g <p> e \ k <l + 0>. Non riesco ancora a vedere cosa? <p> | è però. Non | significa "o"? Non riesco a trovare la documentazione di tale utilizzo per il pipe in REs. Sarei comunque lieto di vedere una spiegazione dettagliata per questo bellissimo RE.
Kevin Ford il sottomarino

5

In realtà è più facile farlo con la manipolazione delle stringhe piuttosto che con le espressioni regolari:

bool isPalindrome(String s1)

{

    String s2 = s1.reverse;

    return s2 == s1;
}

Mi rendo conto che questo non risponde realmente alla domanda dell'intervista, ma potresti usarlo per mostrare come conosci un modo migliore di svolgere un compito e non sei la tipica "persona con un martello, che vede ogni problema come un chiodo . "


Considerando che sono piuttosto appassionato di questa risposta, penso che otterresti punti extra usando BreakIterator per dividere correttamente la stringa in caratteri visivi.
Trejkaz,

5

Ecco la mia risposta al 5 ° livello di Regex Golf (Un uomo, un piano). Funziona fino a 7 caratteri con Regexp del browser (sto usando Chrome 36.0.1985.143).

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

Eccone uno per un massimo di 9 caratteri

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

Per aumentare il numero massimo di caratteri per cui funzionerebbe, sostituiresti ripetutamente . con (?: (.).? \ n?)? .


1
L'ho gestito con un po 'meno di caratteri, ^ (.) (.) (.)?.? \ 3 \ 2 \ 1 $
Ben Ellis

Grazie mille per avermelo rovinato :-)
U10-Forward

Perché il resto delle persone ha 13 ma questo è 19
U10-Forward

5

Le espressioni regolari ricorsive possono farlo!

Così semplice e ovvio algoritmo per rilevare una stringa che contiene un palindromo:

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

Su rexegg.com/regex-recursion il tutorial spiega come funziona.


Funziona bene con qualsiasi linguaggio, qui un esempio adattato dalla stessa fonte (link) come proof-of-concept, 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";
}

uscite

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

Confronto

L'espressione regolare ^((\w)(?:(?1)|\w?)\2)$ fa lo stesso lavoro, ma come sì / no invece "contiene".
PS: sta usando una definizione in cui "o" non è un palimbromo, il formato con trattino "abile-elba" non è un palindromo, ma "abile" lo è. Denominarlo definizione 1 .
Quando "o" e "abile-elba" sono palindroni, denominazione definizione2 .

Confrontando con un'altra "regex palindromo",

  • ^((.)(?:(?1)|.?)\2)$la base-regex sopra senza \wrestrizioni, che accetta "abile-elba".

  • ^((.)(?1)?\2|.)$( @LilDevil ) Usa la definizione2 (accetta "o" e "abile-elba" così differenti anche nel riconoscimento delle stringhe "aaaaa" e "bbbb").

  • ^((.)(?1)\2|.?)$( @Markus ) non ha rilevato "kook" né "bbbb"

  • ^((.)(?1)*\2|.?)$( @Csaba ) Usa definizione 2 .


NOTA: per confrontare puoi aggiungere più parole $subjectse una riga per ogni regex confrontata,

  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

Puoi anche farlo senza usare la ricorsione:

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

per consentire un singolo carattere:

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

Funziona con Perl, PCRE

demo

Per Java:

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

demo


1
Questa è una risposta molto interessante a una domanda regex. In realtà l'unico modello che ha superato alcuni dei miei test . Grazie per questo Casimir :)
bolla bobble

1
@bobblebubble: Grazie per il tuo supporto. Come puoi vedere, ho modificato questa risposta di recente perché la versione precedente era sbagliata (per tre anni, che peccato).
Casimir et Hippolyte

4

Per quanto riguarda l'espressione PCRE (da MizardX):

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

L'hai provato? Sul mio PHP 5.3 sotto Win XP Pro non funziona: aaaba In realtà, ho modificato leggermente l'espressione dell'espressione, per leggere:

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

Penso che quello che sta succedendo sia che mentre la coppia di personaggi esterni è ancorata, i restanti personaggi interni non lo sono. Questa non è esattamente la risposta completa perché mentre trasmette erroneamente "aaaba" e "aabaacaa", fallisce correttamente su "aabaaca".

Mi chiedo se ci sia una soluzione per questo, e inoltre, l'esempio Perl (di JF Sebastian / Zsolt) ha superato correttamente i miei test?

Csaba Gabor di Vienna



3

In Perl (vedi anche la risposta di 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

Come sottolineato da ZCHudson , determinare se qualcosa è un palindromo non può essere fatto con una normale espressione regolare, poiché l'insieme di palindromo non è un linguaggio normale.

Non sono assolutamente d'accordo con Airsource Ltd quando afferma che "non è possibile" non è il tipo di risposta che l'intervistatore sta cercando. Durante il mio colloquio, arrivo a questo tipo di domande quando affronto un buon candidato, per verificare se riesce a trovare l'argomento giusto quando gli abbiamo proposto di fare qualcosa di sbagliato. Non voglio assumere qualcuno che proverà a fare qualcosa nel modo sbagliato se ne conosce uno meglio.



2

Spiegherei all'intervistatore che il linguaggio costituito dai palindromi non è un linguaggio regolare ma invece privo di contesto.

L'espressione regolare che corrisponderebbe a tutti i palindromi sarebbe infinita . Suggerirei invece di limitarsi a una dimensione massima di palindromi da accettare; o se tutti i palindromi sono necessari, usa almeno un qualche tipo di NDPA, o usa semplicemente la semplice tecnica di inversione di stringa / uguale.


2

Il meglio che puoi fare con le espressioni regolari, prima di esaurire i gruppi di acquisizione:

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

Questo corrisponderà a tutti i palindromi fino a 19 caratteri di lunghezza.

Risolvere programmaticamente per tutte le lunghezze è banale:

str == str.reverse ? true : false

La tua regex non funziona. Ad esempio, indicherà che "abac" è una corrispondenza ...
Darwin Airola

2

Non ho ancora il rappresentante per commentare in linea, ma la regex fornita da MizardX e modificata da Csaba può essere modificata ulteriormente per farla funzionare in PCRE. L'unico errore che ho riscontrato è la stringa a un carattere, ma posso verificarlo separatamente.

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

Se riesci a farlo fallire su altre stringhe, per favore commenta.


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

Dalla teoria degli automi è impossibile abbinare un paliandromo di qualsiasi lunghezza (perché ciò richiede una quantità infinita di memoria). Ma È POSSIBILE abbinare i paliandromi di lunghezza fissa. Supponiamo che sia possibile scrivere una regex che corrisponda a tutti i paliandromi di lunghezza <= 5 o <= 6 ecc., Ma non> = 5 ecc. Dove il limite superiore non è chiaro


2

In Ruby puoi usare \b(?'word'(?'letter'[a-z])\g'word'\k'letter+0'|[a-z])\bper abbinare parole palindromo comea, dad, radar, racecar, and redivider . ps: questa regex corrisponde solo a parole palindrome lunghe un numero dispari di lettere.

Vediamo come questa regex corrisponde al radar. Il confine di parola \ b corrisponde all'inizio della stringa. Il motore delle espressioni regolari entra nella "parola" del gruppo di acquisizione. [az] corrisponde a r che viene quindi memorizzato nello stack per la "lettera" del gruppo di cattura al livello di ricorsione zero. Ora il motore regex entra nella prima ricorsione del gruppo "parola". (? 'letter' [az]) corrisponde e acquisisce a al livello di ricorsione uno. La regex entra nella seconda ricorsione del gruppo "parola". (? 'lettera' [az]) acquisisce d al livello di ricorsione due. Durante le due successive ricorsioni, il gruppo acquisisce aer ai livelli tre e quattro. La quinta ricorsione ha esito negativo perché non sono rimasti caratteri nella stringa affinché [az] corrisponda. Il motore di regex deve tornare indietro.

Il motore di regex ora deve provare la seconda alternativa all'interno del gruppo "parola". La seconda [az] nella regex corrisponde alla r finale nella stringa. Il motore ora esce da una ricorsione riuscita, tornando di un livello fino alla terza ricorsione.

Dopo la corrispondenza (& parola) il motore raggiunge \ k'letter + 0 '. Il backreference non riesce perché il motore di regex ha già raggiunto la fine della stringa dell'oggetto. Quindi torna indietro ancora una volta. La seconda alternativa ora corrisponde a a. Il motore di regex esce dalla terza ricorsione.

Il motore di regex ha nuovamente trovato corrispondenza (& word) e deve tentare di nuovo il backreference. Il backreference specifica +0 o il livello attuale di ricorsione, che è 2. A questo livello, il gruppo di acquisizione ha trovato d. Il backreference non riesce perché il carattere successivo nella stringa è r. Tornando ancora indietro, la seconda alternativa corrisponde a d.

Ora, \ k'letter + 0 'corrisponde alla seconda a nella stringa. Questo perché il motore di regex è tornato alla prima ricorsione durante la quale il gruppo di acquisizione ha abbinato il primo a. Il motore di regex esce dalla prima ricorsione.

Il motore di regex è ora di nuovo fuori dalla ricorsione. Che questo livello, il gruppo di cattura memorizzato r. Il backreference può ora corrispondere alla r finale nella stringa. Poiché il motore non è più all'interno di alcuna ricorsione, procede con il resto della regex dopo il gruppo. \ b corrisponde alla fine della stringa. La fine della regex viene raggiunta e il radar viene restituito come corrispondenza complessiva.


2

ecco il codice PL / SQL che dice se la stringa data è palindromo o meno usando espressioni regolari:

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
Sebbene questo codice possa rispondere alla domanda, fornire un contesto aggiuntivo su come e / o perché risolve il problema migliorerebbe il valore a lungo termine della risposta.
Paperino,

2

Questa regex rileverà palindromi fino a 22 caratteri ignorando spazi, tabulazioni, virgole e virgolette.

\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

Gioca con esso qui: https://regexr.com/4tmui


0

Un leggero perfezionamento del metodo di Airsource Ltd, in pseudocodice:

WHILE string.length > 1
    IF /(.)(.*)\1/ matches string
        string = \2
    ELSE
        REJECT
ACCEPT
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.