Suchen Sie in allen Wörtern der Sprache nach Anagrammen und Sabanagrammen

Das Lösen von Problemen mit Anagrammen führte zu der Idee:
Wie viele Wörter bleiben übrig, wenn Sie alle Anagramme und Sangangrams aus dem Wörterbuch der russischen Sprache entfernen

Das Wörterbuch enthält mehr als 1,5 Millionen Wörter in verschiedenen Formen.

Sie können jedes Wort mit jedem vergleichen, aber für 1,5 Millionen Einträge ist es lang und nicht optimal.
In einer Welt mit unendlichem Speicher können Sie Teilzeichenfolgen aller Permutationen jedes Wortes generieren und unser Wörterbuch darauf überprüfen.

Aber gibt es eine bessere Lösung ?

Beginnen wir mit der Terminologie:

Anagramm - ein Wort, das durch Umordnen von Buchstaben erhalten wurde
Beispiel: Rakete und Wagen

Sabanagramm - ein Wort, das aus Buchstaben eines anderen Wortes bestehen kann
Beispiel: Bogen - Sabanagramm des Wortes Rakete

Aufgabe :

Nehmen wir an, unser Wörterbuch besteht aus fünf kniffligen Wörtern:

Rakete , Wagen , Bogen , cat , sputum

Fügen Sie dem Präfixbaum (Trie) ein Wörterbuch hinzu.
Jeder Baumknoten enthält ein Paar: Buchstabe + seine Nummer im Wort.
Die Knoten sind alphabetisch und nach der Häufigkeit des Buchstabens im Wort



Algorithmus sortiert (in vereinfachter Form):

Nehmen Sie das Wort, n.r. cat:

Wir suchen nach Knoten, die mit dem Mindestbuchstaben des Wortes („k“) beginnen.

(In der Abbildung sind solche Knoten lila markiert.)

Sobald wir einen solchen Knoten finden, suchen wir im Teilbaum nach dem Pfad, der die verbleibenden Buchstaben in der erforderlichen Menge enthält.

Im Wort sputum unter Knoten K-1 befindet sich O-2 und T-1, was für unser Wort cat ausreicht .

Der Vorteil einer solchen Datenstruktur besteht darin, dass wir den Teilbaum schnell verlassen können, wenn der Knotenbuchstabe> als der Buchstabe ist, den wir

betrachten. Nachdem wir unser Wörterbuch überprüft haben, haben wir herausgefunden, dass nur Sputum kein Anagramm oder ist Sabanagramm eines anderen Wortes

Java-Code
 public boolean isAnagramOrSubAnagram(Word word) {
        Character minCharacter = word.getMinCharacter();

        Stack<TrieNode> stack = new Stack<>();
        stack.add(root);

        while (!stack.isEmpty()) {
            TrieNode node = stack.pop();

            for (Entry<TrieKey, TrieNode> entry : node.getChildren().entrySet()) {
                char character = entry.getKey().getCharacter();
                if (character < minCharacter) {
                    stack.add(entry.getValue());
                } else if (character > minCharacter) {
                    break;
                } else if (entry.getKey().getCount() >= word.getCharacterCount(minCharacter)) {
                    if (doesMinWordCharacterNodeContainAnagram(entry, word)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }



→ Die Vollversion des Codes mit zwei Wörterbüchern und Tests

PS

Für ein russisches Wörterbuch von 1,5 Millionen, 242399 Wörter in 13 Minuten übrig
Für ein englisches Wörterbuch von 416 Tausend übrig 49251 in 45 Sekunden

Sie können das ursprüngliche Wörterbuch optimieren, indem Sie das aktuelle Wort daraus entfernen, wenn das nächste damit beginnt

All Articles