Wie erkennt dieser Java-Regex Palindrome?

Dies ist der dritte Teil einer Reihe von Artikeln zu Bildungsfragen. Es folgtWie findet dieser Regex Dreieckszahlen? (wo verschachtelte Referenzen zuerst eingeführt werden) undWie können wir a ^ n b ^ n mit Java Regex abgleichen? (wo der Lookahead- "Zähl" -Mechanismus weiter ausgeführt wird). In diesem Teil wird eine spezielle Form von geschachtelten Zusicherungen eingeführt, die es in Kombination mit verschachtelten Referenzen ermöglicht, dass Java Regex mit dem übereinstimmt, was die meisten Leute für "unmöglich" halten: Palindrome !!

Die Sprache der Palindrome ist nicht-regulä; Es ist eigentlich kontextfrei (für ein bestimmtes Alphabet). Die moderne Regex-Implementierung erkennt jedoch mehr als nur reguläre Sprachen, und die rekursiven Muster von Perl / PCRE und die .NET-Bilanzgruppen können Palindrome problemlos erkennen (siehe: Verwandte Fragen).

Die Java-Regex-Engine unterstützt jedoch keine dieser "erweiterten" Funktionen. Und doch "jemand"(*zwinkern) hat den folgenden regulären Ausdruck geschrieben, der die Aufgabe zu erfüllen scheint siehe auch auf ideone.com):

public class Palindrome {
    // asserts that the entirety of the string matches the given pattern
    static String assertEntirety(String pattern) {
        return "(?<=(?=^pattern$).*)".replace("pattern", pattern);
    }

    public static void main(String[] args) {
        final String PALINDROME =
            "(?x) | (?:(.) add)+ chk"
                .replace("add", assertEntirety(".*? (\\1 \\2?)"))
                .replace("chk", assertEntirety("\\2"));

        System.out.println(PALINDROME);
        // (?x) | (?:(.) (?<=(?=^.*? (\1 \2?)$).*))+ (?<=(?=^\2$).*)

        String[] tests = {
            "",     // true
            "x",    // true
            "xx",   // true
            "xy",   // false
            "xyx",  // true
            "xxx",  // true
            "xxyx", // false
            "racecar",                // true
            "step on no pets",        // true
            "aManaPlanaCanalPanaMa",  // true
            "this is impossible",     // FALSE!!!
        };
        for (String test : tests) {
            System.out.printf("[%s] %s%n", test, test.matches(PALINDROME));
        }
    }
}

So scheint das zu funktionieren, aber wie?

Verweisjava.util.regex.Pattern regular-expressions.info / Freespacing(?x), Lookarounds(?=…)/(?<=…), etcCOMMON SENSE ALERT !!!

Dies ist nicht der beste Weg, um Palindrome zu erkennen. es istO(N^3)bestenfalls. Das Durchführen dieser Erkennung in einer allgemeineren Programmiersprache ist effizienter und unkomplizierter.

Du würdest nicht wollenverwende Regex zur Erkennung von Palindromen aus den gleichen Gründen, die Sie nicht möchtenverwende Regex, um Primzahlen zu finden. Das heißt, Sie würdenStudi wie ein nicht-rekursiver nicht-ausgleichender Gruppen-Regex Palindrome aus den gleichen Gründen erkennen kann, wie Sie es tun würdenStudi wie ein regulärer Ausdruck für Primärtests verwendet werden kann: Es macht Spaß, ist herausfordernd und lehrreich.

Verwandte FragenWie überprüfe ich, ob ein String ein Palindrom ist, indem ich reguläre Ausdrücke verwende? - es ist unmöglich"! (es sei denn...Wie überprüfe ich, ob die angegebene Zeichenfolge palindrom ist? - Nicht-Regex-Lösungen in vielen SprachenWie kann man feststellen, ob eine Zahl eine Primzahl mit Regex ist?

Antworten auf die Frage(2)

Ihre Antwort auf die Frage