Hash Function ist eine Funktion, die ein Objekt in eine Kampflinie fester Länge verwandelt. Objekte sind oft ungenau, d.h. Massen, Linien usw.
Im Allgemeinen ist Hex-Funktion eine Druckfunktion, d.h. die Kampflinie ist weniger Information als das ursprüngliche Objekt.
Ist die aufgezeichnete Länge der Schlachtlinie klein, so muss die zerbrochene Linie als unkritische Zahl dargestellt und gespeichert werden. Olympiad-Programmierung bedeutet immer, dass, so werden wir in der Zukunft nur die Tatsache berücksichtigen, dass Hexenakt das Objekt eine Zahl macht.

perfekt. Wir wollen folgende Eigenschaften erfüllen:
(1) Die gleichen Objekte hatten dieselbe xash
(2) Sind die Objekte identisch, so sind die Objekte selbst gleich.

Der erste ist einfach, es ist genug, um den allgemein bestimmten Algorithmus zu fragen.
Aber... Zweite Probleme♪ Wie oben erwähnt, komprimiert Hesh Fusion Objekte. Deshalb arbeitet hier das Dirichle-Prinzip - es wird Fälle geben, in denen zwei verschiedene Objekte den gleichen Fuß haben werden. Das nennt man Konflikt.
Die Hash-Funktionen sind "gut" und "schlecht". "Gut" bietet eine kleine Konfliktwahrscheinlichkeit, aber es ist oft schwierig zu beweisen. Diese Beweise werden auch fallen gelassen.

Pulmonary Xashing:
Wir betrachten den Algorithmus, der eine Sequenz (nummeriert) der Zahlen hat. Die Pfeile fallen auch in diese Definition, einfach unter Berücksichtigung des Symbols als seinen ASCII-Code (der Software-Code ändert nichts, weil die Symbole bereits als Zahlen gespeichert sind).
Zur Berechnung der Schärfenfolge der S-Länge n werden wir folgendes Design berücksichtigen:

pnS0) + pn-1* S1 +n-1 + Sn

wobei p die formale Variable ist.
Ich meine, wir haben S-Sequenz an ein Polynom angepasst.

[Bitte beachten Sie, dass Sie auf anderen Ressourcen im Internet ein weiteres Mitglied sehen können, nämlich S.0) + p * S1 + pn-1 * Sn-1 + pn * SnEs ist auch der richtige Weg, aber ich empfehle die Verwendung der obigen Formel, da es helfen wird, das Hashing der Substrate zu vermeiden, über die wir später sprechen werden.]

Jetzt eine Sash aus S-Sequenz zu bekommen, Legen Sie etwas p in diesen Poly.die als Erde bezeichnet wird. Gleichzeitig werden alle Berechnungen vorgenommen. Änderung (d.h. von jedem arithmetischen Betrieb nehmen wir den Rest der mod Split, die als Modul bezeichnet wird.

Mods Parameter fragt nur, wie viel unsere Hex-Funktion die Sequenz komprimiert. Je mehr Mod ist, desto größer sind die möglichen Hesh-Werte. Und je mehr möglicher Schlauch, desto weniger Wahrscheinlichkeit des Konflikts.
Sagen wir, wir müssen mit tausend Linien arbeiten, von denen jeder denkt, ein Schlauch. Wenn wir ein Modul kleiner als 1.000 nehmen, gibt es ein paar Zeilen in Dyrichle, die dasselbe Chaos haben. So wollen wir immer das größte mögliche Modul wählen. Aber wir vergessen nicht, dass wir mit Zahlen arbeiten, weil es schneller und einfacher ist.

Die Parameter p und mod werden im Voraus ausgewählt. Es wird empfohlen, eine Mod gleich einer einfachen Zahl auszuwählen. Angesichts der vorstehenden Ausführungen wäre es gut, im Bereich 10 eine einfache Zahl zu nehmen.ANHANGso dass Zwischenwiedergabevorgänge lang angelegt werden.
Die Grundlage ist nicht sehr beschränkt auf die Wahl, aber ich würde eine kleine Zahl empfehlen.
[In allen chashing Aufgaben habe ich eine einfache Nummer im Bereich 10 gewählt6und Gesamtzahl im Bereich 10ANHANG Für das Modul war es nie möglich, darunter echte Olympiade. Es gibt jedoch mehrere Blogs auf dem Kraftcode, die dazu bestimmt sind, wie man Parameter für das Heshing abholt und wie man Aufgaben aufbricht, die die Parameter kennen. Wenn du willst, kannst du sie sehen.

Wie sieht es im echten Code aus?
Wir verwenden Gorners Schema, um Hash zu berechnen.
[Wenn du nicht weißt, was es ist, kannst du es lesen. Allgemeine Theorieaber es könnte schwierig sein. Ich empfehle zwei Videos:
(1)Beispiel der Papierzahl
(2)Offenlegung von Formel und Pseudokod
!
lange calc_hash(const string bestandteil s, long p, long mod) {
Länge h = 0;
für (int i = 0; i À s.size(); i++)
h = (h * p + (lang) s[i]) % mod;
♪
Rückkehr h;
♪
Hier ist eine Option, die xash aus der Zeile zu berechnen. Alles wird in der gleichen Weise für die Meißelmassen getan.

Es gibt auch einen Weg, die Wahrscheinlichkeit von Konflikten zu reduzieren. Es ist nur, dass wir die Sequenz eines anderen Parameterpaares blockieren müssen. Für eine Sequenz müssen wir die Xash für die Parameter zählen.1mod1und Parameter (p)2mod2) Dadurch erhalten Sie ein paar Schläuche.1, h2)
In diesem Fall wird es bequem sein, alles paarweise zu halten: Basis (p)1, p2Modul (mod)1mod2) und das Ergebnis der xash wird (h)1, h2) Es wird empfohlen, dass die erforderlichen Dampfbetreiber im Voraus zurückgezahlt werden und dass der Code dann ohne Kopierpaste für die erste und zweite geschrieben werden könnte, als ob er auf den Zahlen betrieben wird.

Berücksichtigen Sie jedoch die Overhead-Kosten der Verwendung von Paaren und was Sie jetzt doppelt so viel wie die Operationen.

Was machen wir dagegen?
Der Hauptzweck der Hash in der Olympischen Programmierung ist eine schnelle Überprüfung der Gleichheit großer Objekte.
Der naive Vergleich der Massen und Linien erfolgt über die Zeit mit ihrer Größe.

Sehen wir folgendes: Sie haben eine Reihe von m Linien, von denen jede die Länge von n ist. Sie haben Q-Anfragen, von denen jeder Sie bitte zu sagen, ob die beiden Zeilen des Kits gleich sind.
Angenommen m = 1.000, n = 1.000, q = 1000000.
Dann wird die naive Entscheidung für O(q*n) arbeiten ~=10ANHANG♪ Sie können die Antwort für jedes Paar von Zeilen vorurteilen und dann können Sie die Anfrage im Moment beantworten, aber es funktioniert für O(m).2*n + q) ~=10ANHANGDas ist zu lange.
Wir benutzen das Jashing, wir hängen jede Linie und für jede Anfrage vergleichen wir den Schlauch anstelle der Leitungen. Es funktioniert für O(m*n + q) ~=106Das ist schnell genug.

Hier zählen wir auf die zweite Eigenschaft, die am Anfang betrachtet wurde. Mit viel Wahrscheinlichkeit beschäftigen wir uns mit den gleichen Objekten, also wählen wir hier eine Top-Strategie. Aber es ist immer noch wichtig zu verstehen, dass du vielleicht nicht in der Lage sein könntest [mit doppeltem Heshing, ich hatte nie so etwas mit dem Üblichen, aber es ist nicht wahr].

Anstatt nur die xash-Sequenz zu zählen, können wir uns an die Bedeutung jedes seiner Präfixe erinnern. Wir weisen darauf hin, dass dies die xash-Werte für Sequenzen gleich dem entsprechenden Präfix sein werden.

Mit einer solchen Struktur kann der Wert der xash für jeden Teilabschnitt dieser Sequenz (im Gegensatz zu vorgegebenen Mengen) schnell berechnet werden.

Wenn wir die Xash des Schnittes zählen wollen [l;r], müssen wir den Hash auf den Präfix r und die Hash auf den l-1 Präfix nehmen, auf p auf r-l+1. Warum macht das Sinn, wenn Sie das Präfix unterschreiben und sehen, was los ist? Ich hoffe, Sie können sich dieses Bild ansehen.



Durch diese Aktionen erhalten wir einen Hash-Unterabschnitt der Anfangssequenz. Dieser ist jedoch gleich, wenn er als Hexe aus der Sequenz desselben Unterabschnitts betrachtet wurde (keine zusätzlichen Schritte sind erforderlich, oder so weiter, um mit anderen Werten zu vergleichen).

Es gibt zwei Punkte zu klären:
(1) Alle möglichen Stufen des Mod-Moduls p sollten im Voraus vorgegeben werden, um schnell auf p zu r-l+1 zu Hause.
(2) Es muss beachtet werden, dass alle Berechnungen Mod-Module sind, so kann es sein, dass wir nach dem Lesen des präfixierten Hesh eine negative Zahl erhalten. Um dies zu vermeiden, können Sie immer einen Mod hinzufügen, bevor Sie ausgehen. Auch vergessen wir nicht, nach dem Haus und allen Einlagen nehmen wir auch den Modul.

Der Code sieht aus wie:
#include Ébits/stdc++++++.h
mit Namespace std;

Typdef long ll;

const int MAXN = 1000003;

/ Basis- und Heashing-Modul
ll p, mod;

/ Präfix und p
ll h[MAXN], pows[MAXN];

// Berechnung des xash-Unterabschnitts [l;r]
ll get_segment_hash(int l, int r) {
zurück (h[r] + mod - h[l - 1] * pows[r - l + 1] % mod) % mod;
♪

int main()
{~}
/ auf irgendeine Weise empfangen p und mod

/ Betreff des Abschlusses p
pows[0] = 1;
für (int i = 0; i Ø MAXN; i+++)
pows[i] = (pows[i - 1] * p) % mod;

/
/ Schlüssel
/

Rückkehr 0;
♪

Wenn wir eine xash Linie A gleich h habenALinie B gleich hB.Dann können wir schnell die xash Linie AV zählen:
HAB= hA* p B. + hB.RP- Zählmodul
ина Bина ist die Länge der Linie B.

Neben den Sequenzen kann auch eine Vielzahl erhitzt werden. Ich meine, eine Reihe von Objekten ohne Reihenfolge. Sie gilt wie folgt:
Hash(A) =?RP- Zählmodul
wobei ord eine Funktion ist, die das Objekt einer Vielzahl seiner absoluten Seriennummer mit allen möglichen Objekten vergleicht (z.B. wenn die Objekte natürliche Zahlen sind, dann ord(x) = x, und wenn die starren lateinischen Buchstaben, dann ord('a') = 1, ord('b') = 2 etc.)

Ich meine, jedes Objekt, das wir den Wert der gleichen Basis auf das Ausmaß der Objektnummer vergleichen und alle diese Werte addieren, um eine ganze Menge Hexen zu erhalten. Wie durch die Formel verstanden, wird die Xash leicht neu berechnet, wenn das Element zu oder von ihm entfernt wird (just addiert oder abgezogen). Die gleiche Logik, wenn nicht einzelne Elemente hinzugefügt oder entfernt werden, aber andere Vielfache (nur hinzufügen/lesen sie xash).

Wie Sie vielleicht bereits verstanden haben, gelten einzelne Elemente als eine Vielzahl von Größen 1, für die wir als Schlauch zählen können. Und die größeren Zahlen sind einfach eine Gruppierung von so vielen Singles, wo wir die Lose vereinen, wir zittern sie.

Es ist eigentlich der gleiche Polynomschlauch, aber es ist ein p Koeffizient vorher.mWir hatten den Wert des Sequenzelements n - m - 1 (wo n die Sequenzlänge ist), und jetzt ist es die Anzahl der Elemente in einer Vielzahl, die eine absolute Ordnungszahl von m aufweisen.

Ein solches Jashing erfordert eine ausreichend große Basis (mehr als die maximale Größe der Vielzahl) oder eine doppelte Hexung, um Situationen zu vermeiden, in denen viele der p Objekte mit absoluter Ordnungszahl m die gleiche Chash wie viele mit dem gleichen Objekt mit der absoluten Ordnungszahl m+1 haben.

Es gibt auch mehrere Möglichkeiten, effektiv Wurzelbäume zu schlauchen.
Eine solche Methode ist wie folgt:
Die Tops werden zur Umgehung verarbeitet. Nehmen wir an, dass der Schlauch ein einziges Top gleich p ist. Für die Spitze der Kinder, beginnen wir Algorithmen für sie zuerst, und dann durch die Kinder, werden wir als aktuelle Hash zählen. Zu diesem Zweck werden wir den Schlauch der Kinderunterstützung als Zahlenfolge betrachten und den Schlauch aus dieser Reihenfolge betrachten. Das wird ein Schlauch der aktuellen Unterstützung.
Wenn wir uns nicht um die Kinderordnung kümmern, dann werden wir die Hash-Sequenz vor der Kinderunterstützung verzerren und dann das Chaos auf die verzerrte Sequenz zählen.

So können Sie die Isomorphiken der Bäume überprüfen - denken Sie nur, dass die Chash ist aus Ordnung für die Kinder (d.h., jedes Mal, wenn wir die Xash der Kinder sortieren). Und wenn die Schlauchwurzeln passen, die Bäume des Isomorphnes, ansonsten nein.

Für nicht-indigene Bäume ist alles ähnlich, aber Centoide müssen als Wurzel genommen werden. Oder betrachten Sie ein paar Schläuche, wenn die Zentrifuge zwei ist.