Vraagt u zich af de meest efficiënte manier om een binaire zoekboom in een spellingscontrole te maken door het inlezen van bijvoorbeeld 1000 woord woordenboek-bestand en dan het hebben van het een ander document dat zeggen heeft een paar alinea's te controleren.
Met behulp van een binaire zoekboom als een spellingcontrole
een ternair boom trie zou efficiënter zijn
Als u een auto suggereren / prefix zoeken ook, dan is een patricia boom of radix boom is de moeite waard te kijken naar.
Met het voorbeeld dat je gaf, de prestaties is waarschijnlijk irrelevant zijn, omdat op een PC de hele operatie ongeveer 1% van de tijd die het kost de gebruiker in staat om het eerste resultaat te laten zien leest zal nemen, op voorwaarde dat u geen gebruik maken van een heel domme algoritme . Maar toch, ik neem aan dat het probleem is groot genoeg dat de prestaties is een probleem.
Als het woordenboek bestand wordt voorgesorteerd (zoals de meeste zijn), en als de tekst is klein ten opzichte van het woordenboek als u beschrijft, dan zou ik zwaar in de verleiding om de tekst te sorteren, misschien het verwijderen van duplicaten, en vervolgens doorloopt beide lijsten side-by -side volgens dezelfde procedure als een merge soort, behalve dat u rapporteren of elke tekst woord in het woordenboek in plaats van het uitvoeren van een samengevoegde lijst.
Dit doet het werk in ongeveer M log M vergelijkingen voor het soort, plus ten hoogste N + M vergelijkingen voor de iteratie, (misschien minder, maar niet complexiteit-minder). Dat is vrij dicht bij een optimale complexiteit voor een eenmalige operatie: om zich te ontdoen van de lineaire term in N u moeten manieren vinden om niet lezen het hele woordenboek van schijf helemaal vinden te krijgen. Ik ben er vrij zeker van dat het mogelijk is om Bsearch in het bestand, vooral gezien het feit dat woorden zijn vrij kort, maar voor de kleine N het is iedereen een raadsel of op zoek over de plaats ook daadwerkelijk sneller dan serieel toegang tot de gegevens.
Het heeft de volgende kenmerken:
- Je hoeft niet naar het woordenboek in het geheugen, alleen de tekst te houden.
- Toch bent u alleen maar één bal schitterend in het woordenboek bestand.
- Je hebt geen dure bewerking van het woordenboek te doen.
Natuurlijk, als het woordenboek bestand is niet voorgesorteerd dan is dit niet werkt, en als je het woordenboek opknoping rond in het geheugen voor de volgende spellingscontrole operatie kan houden dan kunt u de kosten van de I / O af te schrijven en het verwerken van het in een boom over verschillende teksten, die een overwinning op de lange termijn zal zijn.
Als het woordenboek is echt enorm, dan kun je profiteren van de op te slaan op de harde schijf in een pre-bewerkte vorm die gelijkwaardig zijn aan een onevenwichtige boom gewogen op basis van de relatieve frequenties van de verschillende woorden in uw taal. Dan kunt u minder dan O (N) disk toegang voor kleine teksten te doen, en op de meeste besturingssystemen niet de moeite laden in het geheugen helemaal niet, net mmap het bestand en laat de OS zorgen over te maken. Voor een groot woordenboek, het hele clusters die woorden bevatten die beginnen met "dimethyl" hoeft nooit te worden aangeraakt.
Een andere overweging is een splayboom voor het woordenboek. Een splayboom onevenwichtigheden zich als je dingen opzoeken in het, met het oog op veelgebruikte waarden sneller te kunnen vinden. De meeste tekst maakt gebruik van een klein aantal woorden herhaaldelijk, dus als de tekst is lang genoeg om de overhead te rechtvaardigen zal dit uiteindelijk winnen.
Zowel van de bovenstaande tijden zijn afhankelijk punt van Steven A Lowe die voor strijkers, een trie slaat een gewone boom. Weet niet of je een off-the-shelf splay trie zult vinden, dat wel.
Als je gewoon proberen om te zien of een bepaald woord in uw woordenboek bestaat (dat wil zeggen, het correct gespeld), dan denk ik niet dat een binaire zoekboom is wat je zoekt. Een betere manier om die informatie op te slaan zou zijn in een boom stijl, waar elke volgende knooppunt op uw boom is een karakter, en het lezen van het pad naar het einde knooppunt geeft u de spelling van dat woord. Je zou ook nodig zijn om een marker toe te voegen aan een woord-einde aan te geven.
Bijvoorbeeld: zeg uw woordenboek heeft deze woorden: auto, kar, kat, beker, gesneden
- C
- A
- R
- end
- T
- T
- end
- U
- P
- end
- T
- end
Controleren of een woord bestaat, is een kwestie van kijken naar elke letter afzonderlijk, en dat het bestaat in de kinderen van het huidige knooppunt.
Check for "cat"
Does "C" exist at the root level? Yes, move to the next letter.
Does "A" exist underneath C? Yes, move on.
Does "T" exist underneath A? Yes, move on.
Is there a word ending after the T? Yes. Word exists.
Check for "cu"
Does "C" exist at the root level? Yes, move to the next letter.
Does "U" exist at the root level? Yes, move to the next letter.
Is there a word ending after the U? No. Word does not exist.
Hoe u op te slaan deze informatie is aan jou. Zoals Steven opgemerkt, een ternaire Search Trie elk knooppunt zou 27 mogelijk kind knooppunten: kan de weg te gaan.
Ben je dood ingesteld op het gebruik van een binaire zoekboom? Een Bloom filter zou waarschijnlijk een meer efficiënte data structuur.
Aangezien dit is een huiswerk vraag die ik ga ervan uit dat je een gewone oude binaire boom (geen rood-zwarte bomen, AVL bomen, Radix bomen, etc.). Het antwoord is dan om te proberen om de boom in balans te houden zoals u het bouwen van de woordenlijst. Een benadering is om de lijst willekeurig voorafgaand aan in het lezen, dit geeft redelijke resultaten. Maar je kunt betere resultaten krijgen als u de inkomende opeenvolging (met dezelfde vergelijking als wat de boom gebruikt) bestelt, dan recursief onderverdelen de ingang terug te keren het middelpunt tot er geen elementen blijven. Het resultaat is een evenwichtige boom.
Ik klopte op drie verschillende manieren om het te doen in C #:
private static IEnumerable<T> BinaryTreeOrder<T>(IList<T> range, int first, int last)
{
if (first > last)
{
yield break;
}
int mid = (first + last) / 2;
yield return range[mid];
foreach (var item in BinaryTreeOrder(range, first, mid - 1))
{
yield return item;
}
foreach (var item in BinaryTreeOrder(range, mid + 1, last))
{
yield return item;
}
}
private static void BinaryTreeOrder<T>(IList<T> range, int first, int last,
ref IList<T> outList)
{
if (first > last)
{
return;
}
int mid = (first + last) / 2;
outList.Add(range[mid]);
BinaryTreeOrder(range, first, mid - 1, ref outList);
BinaryTreeOrder(range, mid + 1, last, ref outList);
}
private static void BinaryTreeOrder<T>(IList<T> range, int first, int last,
ref BinaryTree<T> tree) where T : IComparable<T>
{
if (first > last)
{
return;
}
int mid = (first + last) / 2;
tree.Add(range[mid]);
BinaryTreeOrder(range, first, mid - 1, ref tree);
BinaryTreeOrder(range, mid + 1, last, ref tree);
}
Deze site moet u te helpen heeft de implementatie in Java.
Zoals voorgesteld een trie efficiënter dan een binaire boom zou zijn, maar u kunt een HashMap gebruiken en hash elk woord. Je hebt een klein woordenboek (1000 nummers). Als u uw document doorkruisen, controleer dan of de woorden zijn in de HashMap. Als ze niet, dan wordt het woord aangenomen dat verkeerd gespeld.
Dit zal u niet eventuele correctie te geven aan een verkeerd gespelde woord. Het vertelt je gewoon ja of nee (correct of niet).
Als u wilt dat de spelling suggesties voor onjuiste woorden die u kunt starten vanaf het woord in het bestand, dan is het genereren van alle woorden 1 bewerken afstand en voeg deze toe als kinderen van het eerste woord. Deze manier bent u het opbouwen van een grafiek. Go 2 niveaus diep voor maximale snelheid versus nauwkeurigheid. Als u een woord knooppunt dat in het woordenboek te genereren, kunt u deze toevoegen aan een lijst met mogelijke suggesties. Aan het einde, de terugkeer van de lijst met mogelijke suggesties.
Voor een betere spellingcontrole, ook proberen om toe te voegen in fonetische matching.
zee yuh -> zie yah
Deze methode (het creëren van grafieken van strings 1 bewerken afstand) is "langzaam". Maar het is een goede academische oefening. Runtime O (n vertakkingen).
Als hier geïnteresseerd is een link naar een bouwde ik mezelf (voor de lol): https://github.com/eamocanu/spellcheck.graph
Enkele voorbeelden grafieken: https://github.com/eamocanu/spellcheck.graph/tree/master/graph%20photos
Ik heb ook een UI component in te zetten die de grafieken genereert. Dit is een externe bibliotheek.













