Barre
Bor est une structure de données pour stocker un ensemble de chaînes, qui est un arbre enraciné avec des symboles sur les bords. < /div>
Chaque sommet de bore correspond à un préfixe d'une chaîne ajoutée. Ce préfixe lui-même est obtenu en écrivant séquentiellement des caractères sur les arêtes du chemin de la racine à ce sommet. En même temps, exactement un sommet correspond à chaque préfixe existant. Bor root correspond à une chaîne vide.
Exemple de bore pour {be, bee, can, cat, cd}
L'orange indique les sommets qui correspondent aux mots de l'ensemble eux-mêmes. Ils sont appelés terminaux.
Vous trouverez ci-dessous le code permettant de stocker le bore et d'y ajouter des lignes. Cette méthode stocke l'alésage à travers un tableau. Il existe également une implémentation via des pointeurs, qui est présentée dans le code de la tâche pour l'entraînement.
// taille de l'alphabet en mots considérés
const entier alpha = 26 ;
// structure pour le haut du foret
structure Noeud{
// vecteur d'arêtes sous forme de tableau d'adjacence, soit :
// next[0] - enfant lors du saut par-dessus le caractère numéro 0 ('a')
// next[1] - enfant lors du saut par-dessus le caractère numéro 1 ('b')
// etc.
vecteursuivant ;
// Options supplémentaires
// dans ce cas, la hauteur du sommet h et le drapeau de terminalité
entier h ;
terme booléen;;
Noeud(int h) {
next.resize(alph, -1); // initialement sans arêtes
ceci->h = h ; // la hauteur est égale à celle spécifiée
terme=faux ; // top n'est pas terminal par défaut
}
} ;
// liste des sommets, initialement racine à hauteur nulle
vecteur trie(1, nœud(0));
// fonction pour ajouter une chaîne au bore
void add(const string& s) {
entier v = 0 ; // numéro du sommet courant, en partant de la racine
forn(je, (int)s.taille()) {
int c = s[i] - 'a'; // récupère le numéro du caractère courant dans la chaîne
// si la transition souhaitée n'existe pas encore, alors nous en créerons une nouvelle
si (trie[v].next[c] == -1) {
trie[v].next[c] = (int)trie.size(); // le nouveau numéro de sommet est
// taille de perçage actuelle (avec numérotation 0)
trie.push_back(Node(trie[v].h + 1)); // crée un nouveau sommet de hauteur 1 de plus
}
v = trie[v].next[c] ; // se déplacer le long du bord désiré
}
// quand nous sommes arrivés au sommet,
// qui correspond à la chaîne entière,
// puis marquez-le comme terminal
trie[v].term = vrai ;
}
Si vous devez soutenir la suppression de lignes du bore, cela se révélera probablement malhonnête. Autrement dit, supprimez simplement le drapeau terminal (ou, peut-être, au lieu du drapeau, vous devrez stocker un nombre variable) et laissez l'arbre de bore lui-même inchangé.
Ainsi, les insertions/recherches/suppressions abusives fonctionnent en temps linéaire à partir de la longueur de la chaîne de requête.
Le bore lui-même, dans le pire des cas, occupera la mémoire O(n|Σ|) , où n est la longueur totale de toutes les chaînes, et Σ > - l'alphabet des chaînes utilisées.
|
Pour résoudre ce problème, la théorie de l'analyse des jeux vous aidera grandement : https://e-maxx.ru/algo/games_on_graphs
|