Wie funktioniert das Java-regex erkennen Palindrome?

Dies ist der Dritte Teil in einer Reihe von Bildungs-regex-Artikel. Es folgt Wie funktioniert dieser regex finden, dreieckige zahlen? (wo verschachtelten Referenzen wird vorgestellt) und Wie können wir mit a^n b^n mit Java-regex?
(wo die lookahead - "counting" - Mechanismus wird weiter herausgearbeitet). Dieser Teil stellt eine spezifische form der geschachtelten Behauptung, die, wenn Sie kombiniert mit verschachtelten Referenzen ermöglicht Java-regex-match, was die meisten Menschen glauben, dass es "unmöglich": Palindrome!!

Die Sprache der Palindrome ist nichtregelmäßige; es ist tatsächlich Kontext-frei (für ein gegebenes alphabet). Das heißt, die modernen regex-Implementierung erkennt mehr als nur die regulären Sprachen, und Perl/PCRE die rekursive Muster und .NET-balancing-groups können leicht erkennen Palindrome (siehe: Fragen).

Jedoch Java-regex-engine unterstützt keine dieser "erweiterte" Funktionen. Und noch "jemand" (*wink*) geschafft zu schreiben, der folgende regex, die scheint, um den job zu erledigen just fine (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));
        }
    }
}

Also das scheint zu funktionieren, aber wie?

Referenzen


DER GESUNDE MENSCHENVERSTAND ALARM!!!!!

Dies ist nicht der beste Weg, um erkennen Palindrome; es ist O(N^3)am besten. Die Durchführung dieser Fund in einer mehr Allzweck-Programmiersprache ist effizienter und einfacher.

Würden Sie nicht wollen, um verwenden regex zu erkennen Palindrome aus den gleichen Gründen, die Sie würde nicht wollen, zu verwenden regex zum finden von Primzahlen. Das heißt, Sie würden Studie, wie ein nicht-rekursiver, nicht-bilanzkreis regex erkennen kann, Palindrome aus den gleichen Gründen würden Sie Studie, wie ein regex verwendet werden kann für primality testing: es macht Spaß, es ist herausfordernd, es ist lehrreich.

Fragen

  • Diskussion der Serie: meta.stackexchange.com/questions/62695/... ; Auch, kein Zweifel, es sind Tippfehler/Fehler, die in diesem langen Artikel. Bitte hinterlassen Sie Kommentare und feedbacks, wie ich es Tue-plan ständig aktualisiert.
  • Ich möchte nur erwähnen, dass die Verwendung von regulären Ausdrücken zu erkennen Palindrome ist eine besonders dumme Idee. Es gibt viel bessere Möglichkeiten, es zu tun. Verwenden Sie dies, um sich selbst zu erziehen, die auf regulären Ausdrücken, sondern Teil der Bildung ist, zu wissen, wenn Sie nicht zu verwenden. Nicht versuchen, den Regen auf Ihrer parade, @poly, ich bin sicher, dies ist ein guter Artikel 🙂
  • Dieser Artikel ist nicht wirklich über Palindrome, für fast den gleichen Gründen, die Fabeln sind nicht wirklich darüber reden, Löwen-und/oder Gesang Esel. Es gibt Moral und Lektionen, hier gewesen zu sein, und betrachten dies als nur ein Palindrom Erkennung regex-lediglich Kratzer an der Oberfläche.
  • Ich Stimme mit @paxdiablo und möchte hinzufügen, dass zu tun, komplizierte Dinge allgemein mit regexes ist eine dumme / schlechte Idee. IMO, dieses Frage / Antwort sollte vorangestellt werden, die Warnung NICHT TUN in blinkende rote Punkt 26 Großbuchstaben.
  • Ich denke, es gibt einen GROßEN Unterschied zwischen den Fragen "Wie muss ich Parsen dieses XML-fragment mit regex?" und "Wie können wir erkennen Palindrome mit (Java -) regex?". Mit der ehemaligen, die Leute wissen es nicht besser, aber mit der letzteren, die Menschen wissen es nicht die beste Lösung, sondern Sie Fragen, weil Sie lernen wollen. Dies ist die gleiche treibende motivation, fasziniert die Menschen zu verstehen, z.B. primality Prüfung mit regex. Es ist OFFENSICHTLICH nicht die "richtige" Lösung, sondern es ist untrennbar mit Bildung. Das heißt, ich füge ein "COMMON SENSE ALERT" - Warnung auf der nächsten revision irgendwann später heute.
  • Ich bin glücklich mit dieser Frage, gegeben, dass es nicht die Regeln zu befolgen, wie es in der FAQ. Ich würde mich auch hassen zu sehen, es gehen, weil nur so verdammt viel Arbeit in ihm und die Antwort. Ich wurde nur darauf hin, dass Palindrom-Erkennung mit einem regex war nicht die beste Verwendung von es. Wahrscheinlich hätte ich nicht so kritisch, wenn ich die Zeit hatte, um das ganze zu Lesen, anstatt nur den Titel und das erste para 🙂
  • Teil 4: stackoverflow.com/questions/3693698/...

Schreibe einen Kommentar