Estou interessado em tentativas e DAWGs (gráfico de palavras acíclicas diretas) e tenho lido muito sobre eles, mas não entendo como deve ser a trie de saída ou o arquivo DAWG.
- Um trie deve ser um objeto de dicionários aninhados? Onde cada letra é dividida em letras e assim por diante?
- Uma pesquisa realizada nesse dicionário seria rápida se houver entradas de 100k ou 500k?
- Como implementar blocos de palavras que consistem em mais de uma palavra separada por
-
ou espaço? - Como vincular prefixo ou sufixo de uma palavra a outra parte da estrutura? (para DAWG)
Quero entender a melhor estrutura de saída para descobrir como criar e usar uma.
Eu também apreciaria qual deveria ser a saída de um DAWG junto com trie .
Não quero ver representações gráficas com bolhas ligadas entre si, quero conhecer o objeto de saída assim que um conjunto de palavras for transformado em tentativa ou DAWG.
Respostas:
Desenrolar é essencialmente correto que existem muitas maneiras diferentes de implementar uma tentativa; e, para uma tentativa grande e escalável, os dicionários aninhados podem se tornar pesados - ou pelo menos ineficientes em termos de espaço. Mas como você está apenas começando, acho que é a abordagem mais fácil; você pode codificar um simples
trie
em apenas algumas linhas. Primeiro, uma função para construir o trie:Se você não estiver familiarizado
setdefault
, basta procurar uma chave no dicionário (aquiletter
ou_end
). Se a chave estiver presente, ela retornará o valor associado; caso contrário, atribui um valor padrão a essa chave e retorna o valor ({}
ou_end
). (É como uma versãoget
que também atualiza o dicionário.)Em seguida, uma função para testar se a palavra está no seguinte:
Deixarei inserção e remoção para você como um exercício.
Obviamente, a sugestão de Unwind não seria muito mais difícil. Pode haver uma ligeira desvantagem de velocidade, pois encontrar o subnó correto exigiria uma pesquisa linear. Mas a pesquisa seria limitada ao número de caracteres possíveis - 27, se incluirmos
_end
. Além disso, não há nada a ganhar criando uma lista enorme de nós e acessando-os por índice, como ele sugere; você pode apenas aninhar as listas.Por fim, acrescentarei que a criação de um gráfico de palavras acíclicas direcionadas (DAWG) seria um pouco mais complexa, porque você precisa detectar situações nas quais sua palavra atual compartilha um sufixo com outra palavra na estrutura. De fato, isso pode ficar bastante complexo, dependendo de como você deseja estruturar o DAWG! Talvez você precise aprender algumas coisas sobre a distância de Levenshtein para acertar.
fonte
dict.setdefault()
(é subutilizado e não é bem conhecido o suficiente), em parte porque ajuda a evitar bugs que são fáceis de criar com umdefaultdict
(onde você não obteriaKeyError
chaves inexistentes na indexação). A única coisa agora que iria torná-lo utilizável para o código de produção está usando_end = object()
:-)Veja isso:
https://github.com/kmike/marisa-trie
Aqui está uma postagem de blog de uma empresa que usa marisa trie com sucesso:
https://www.repustate.com/blog/sharing-large-data-structure-across-processes-python/
Existem também algumas implementações de python puro, embora, a menos que você esteja em uma plataforma restrita, você queira usar a implementação suportada em C ++ acima para obter melhor desempenho:
fonte
Aqui está uma lista de pacotes python que implementam o Trie:
fonte
Modificado a partir
senderle
do método (acima). Eu descobri que o Pythondefaultdict
é ideal para criar uma árvore trie ou prefixo.fonte
Não há "deveria"; você decide. Várias implementações terão características de desempenho diferentes, levarão várias quantidades de tempo para implementar, entender e acertar. Isso é típico para o desenvolvimento de software como um todo, na minha opinião.
Eu provavelmente tentaria primeiro criar uma lista global de todos os nós até agora criados e representar os ponteiros filhos em cada nó como uma lista de índices na lista global. Ter um dicionário apenas para representar a ligação entre crianças parece muito pesado para mim.
fonte
Se você deseja que um TRIE seja implementado como uma classe Python, aqui está algo que escrevi depois de ler sobre eles:
fonte
Esta versão está usando recursão
Resultado:
fonte
Definir Trie:
Crie Trie:
Olho para cima:
Teste:
fonte
True
somente para uma palavra inteira, mas não para prefixo, para a mudança de prefixoreturn '_end' in curr
areturn True
Fora
fonte
Classe Python para Trie
A estrutura de dados Trie pode ser usada para armazenar dados em
O(L)
que L é o comprimento da string, portanto, para inserir N strings, a complexidade do tempo seria queO(NL)
a string pudesse ser pesquisada daO(L)
mesma maneira que a exclusão.Pode ser clonado em https://github.com/Parikshit22/pytrie.git
Code Oputpt
True
False
['minakshi', 'minhaj']
7
minakshi
minhajsir
pari
parikshit
shubh
shubham
shubhi
fonte