Barra
Bor é uma estrutura de dados para armazenar um conjunto de strings, que é uma árvore enraizada com símbolos nas bordas. < /div>
Cada vértice de boro corresponde a um prefixo de alguma string adicionada. Esse prefixo em si é obtido escrevendo caracteres sequencialmente nas arestas do caminho da raiz até esse vértice. Ao mesmo tempo, exatamente um vértice corresponde a cada prefixo existente. Bou root corresponde a uma string vazia.
Exemplo de boro para {be, bee, can, cat, cd}
Laranja indica os vértices que correspondem às palavras do próprio conjunto. Eles são chamados terminais.
Abaixo está o código para armazenar o boro e adicionar linhas a ele. Este método armazena o furo por meio de uma matriz. Existe também uma implementação através de ponteiros, que é apresentada no código da tarefa para treinamento.
// tamanho do alfabeto em palavras consideradas
const int alfa = 26;
// estrutura para o topo da furadeira
struct Nó{
// vetor de arestas em forma de tabela de adjacência, ou seja:
// próximo[0] - filho ao pular sobre o caractere número 0 ('a')
// próximo[1] - filho ao pular sobre o personagem número 1 ('b')
// etc.
vetorpróximo;
// Opções extras
// neste caso, a altura do vértice h e o sinalizador de terminalidade
int h;
termo bool;;
Nó(int h) {
next.resize(alph, -1); // inicialmente sem arestas
este->h = h; // altura é igual a especificada
termo=falso; // top não é terminal por padrão
}
};
// lista de vértices, inicialmente raiz na altura zero
vetor trie(1, Nó(0));
// função para adicionar uma string ao boro
void add(const string& s) {
int v = 0; // número do vértice atual, começando pela raiz
forn(i, (int)s.size()) {
int c = s[i] - 'a'; // obtém o número do caractere atual na string
// se a transição desejada ainda não existe, então faremos uma nova
if (trie[v].next[c] == -1) {
trie[v].next[c] = (int)trie.size(); // o novo número do vértice é
// tamanho do drill atual (com numeração 0)
trie.push_back(Node(trie[v].h + 1)); // cria um novo vértice com altura 1 a mais
}
v = trie[v].próximo[c]; // move ao longo da aresta desejada
}
// quando chegamos ao topo,
// que corresponde a toda a string,
// em seguida, marque-o como terminal
trie[v].termo = verdadeiro;
}
Se você precisar apoiar a exclusão de linhas do boro, provavelmente será desonesto. Ou seja, simplesmente remova o sinalizador terminal (ou, talvez, em vez do sinalizador, você precisará armazenar um número variável) e deixe a própria árvore de boro inalterada.
Assim, inserção/pesquisa/exclusão injusta funcionam em tempo linear a partir do comprimento da string de consulta.
O próprio boro, no pior caso, ocupará a memória O(n|Σ|) , onde n é o comprimento total de todas as strings e Σ > - o alfabeto das strings usadas.
|
Para resolver esse problema, a teoria da análise de jogos o ajudará muito: https://e-maxx.ru/algo/games_on_graphs
|