Vă întrebați modul cel mai EFICIENTĂ pentru a face un arbore binar de căutare într-un corector ortografic citind în 1000 să zicem cuvânt de dicționar fișier și având apoi să verificați un alt document care spune are câteva paragrafe.
Folosind un binar de căutare copac ca un corector ortografic
un arbore ternar trie ar fi mai eficient
Dacă aveți nevoie pentru a face un auto sugerează căutare / prefix, de asemenea, apoi un copac copac sau Radix Patriciei este în valoare de uita la.
Cu exemplul ai dat, performanța este probabil să fie lipsită de relevanță, din moment ce pe un PC întreaga operațiune va dura aproximativ 1% din timpul necesar utilizatorului pentru a citi primul rezultat a vă arăta, cu condiția să nu utilizați un algoritm complet stupid . Dar totuși, voi presupune că problema este destul de mare că performanța este o problemă.
În cazul în care dicționarul fișierul este Pre-sortate (ca cele mai multe sunt), iar în cazul în care textul este relativ mic la dicționar așa cum ați descrie, atunci aș fi extrem de tentate pentru a sorta textul, probabil, eliminarea duplicatelor, și apoi iterează prin ambele liste side-by -side, folosind aceeași procedură ca un fel de îmbinare, cu excepția faptului că un raport dacă fiecare cuvânt de text este în dicționar în loc de o listă scoate îmbinată.
Acest lucru are loc de muncă în aproximativ M comparații log M pentru un fel, plus la cele mai multe comparații N + M pentru iterație, (eventual mai puțin, dar nu și complexitate mai puțin). Asta e destul de aproape de complexitate optimă pentru o operațiune de one-off: pentru a scăpa de termenul liniar în N trebuie să găsească modalități de a nu citi întregul dicționar de pe disc la toate. Sunt destul de sigur că e posibil să bsearch în dosar, mai ales având în vedere că cuvintele sunt destul de scurt, dar pentru mici N este știe nimeni dacă caută despre locul va fi de fapt mai rapid decât accesarea în serie a datelor.
Acesta are următoarele caracteristici:
- Nu trebuie să țineți dicționarul în memorie, numai textul.
- Cu toate acestea, a face doar o singură trecere peste dicționarul fișierul.
- Tu nu faci nici o prelucrare costisitoare a dicționarului.
Desigur, în cazul în care fișierul dicționar nu este pre-sortate, atunci acest lucru nu funcționează, și dacă vă puteți păstra dicționarul agățat în jurul valorii în memorie pentru următoarea operație de Spellcheck atunci puteți amortizeze costul I / O și de prelucrare a acestuia în un copac în mai multe texte diferite, care va fi un câștig pe termen lung.
Dacă dicționarul este într-adevăr foarte mare, atunci s-ar putea beneficia de o stocați pe disc într-o formă de pre-prelucrată echivalent cu un arbore dezechilibrat ponderate în funcție de frecvențele relative ale diferitelor cuvinte în limba dumneavoastră. Apoi, puteți face mai puțin de O (N) de acces pe disc pentru texte mici, iar pe cele mai multe sisteme de operare nu deranjez încărcând-o în memorie, la toate, mmap doar fișierul și lăsați sistemul de operare vă faceți griji cu privire la aceasta. Pentru un dicționar mare, întregul clustere care conțin cuvinte care încep cu „dimetil“ nu trebuie să fie atins.
Un alt considerent este un arbore splay pentru dicționar. Un copac evazat se dezechilibrează ca te uiti lucrurile în ea, în scopul de a face valorile utilizate frecvent pentru a găsi mai repede. Cele mai multe texte utilizează un număr mic de cuvinte în mod repetat, astfel încât în cazul în care textul este suficient de lung pentru a justifica acest lucru deasupra capului va câștiga în cele din urmă.
Ambele cele de mai sus sunt supuse punctul de Steven A Lowe că pentru siruri de caractere, un trie bate un copac normal. Nu știu dacă veți găsi un evazat Trie off-the-shelf, totuși.
Dacă sunteți doar încercarea de a vedea dacă există un anumit cuvânt din dicționar (adică, este scris corect), atunci nu cred că un arbore binar de căutare este ceea ce ești după. O modalitate mai bună de a stoca aceste informații ar fi într-un stil arbore în care fiecare nod succesive pe arborele este un caracter, și citind calea către nodul final vă oferă ortografia acelui cuvânt. De asemenea, ai nevoie să adăugați un marker pentru a indica un cuvânt sfârșit.
De exemplu: spune dicționarul are aceste cuvinte: masina, coș, pisica, cupa, tăiate
- C
- A
- R
- end
- T
- T
- end
- U
- P
- end
- T
- end
Verificarea dacă există un cuvânt este o chestiune de a privi fiecare literă în mod individual, și că există în fiii nodului curent.
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.
Cum stocați această informație este de până la tine. După cum a subliniat Steven, un ternare de căutare Trie ar putea fi calea de a merge: fiecare nod ar avea 27 de noduri posibile pentru copii.
Ești mort-setat pe folosind un arbore binar de căutare? Un filtru Bloom ar fi , probabil , o structură mai eficientă a datelor.
Văzând că aceasta este o întrebare temele am de gând să presupunem că trebuie să utilizați un copac simplu vechi binar (fără copaci rosu-negru, copaci AVL, copaci Radix, etc). Răspunsul atunci este de a încerca să păstreze copac echilibrat, așa cum se va construi din lista de cuvinte. O abordare este de a ȋntamplare lista înainte de a citi-o în, acest lucru dă rezultate rezonabile. Dar puteți obține rezultate mai bune, dacă pentru secvența de intrare (folosind aceeași comparație cu ceea ce folosește copac), apoi subdiviza recursiv de intrare se întoarce la punctul median până când nu rămân elemente. Rezultatul este un arbore echilibrat.
Am bătut până la trei moduri diferite de a face aceasta în 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);
}
Acest site - ul ar trebui să vă ajute are punerea în aplicare în Java.
După cum a sugerat un trie ar fi mai eficient decât un arbore binar, dar puteți utiliza un HashMap și hash fiecare cuvânt. Ai un dicționar mic (1000 de intrări). Pe măsură ce traversa documentul, verificați dacă cuvintele sunt în HashMap. Dacă nu sunt, cuvântul se presupune a fi scrise greșit.
Acest lucru nu vă va da posibilitatea de corecție a unui cuvânt scris greșit. Pur și simplu vă spune da sau nu (corect sau nu).
Dacă doriți sugestii de ortografie pentru cuvinte incorecte puteți începe de la cuvântul în fișierul, apoi genera toate cuvintele 1 edita distanță și se adaugă ca și copii ale cuvântului inițial. În acest fel vă construiți un grafic. Du-te 2 nivele de adâncime pentru viteza maximă față de precizie. Dacă generați un nod cuvânt care este în dicționar, îl puteți adăuga la o listă de posibile sugestii. La final, a reveni lista de posibile sugestii.
Pentru o mai bună verificare a ortografiei de asemenea, încercați să adăugați în potrivirea fonetic.
mare Yuh -> vezi Yah
Această metodă (de creare a graficelor de siruri de 1 edita distanță) este „lent“. Dar este un exercițiu academic bun. Compresia este O (n ^ ramuri).
Daca sunteti interesati aici este un link către una m - am construit (pentru distracție): https://github.com/eamocanu/spellcheck.graph
Unele grafice eșantion: https://github.com/eamocanu/spellcheck.graph/tree/master/graph%20photos
Am adăugat, de asemenea, o componentă UI la acesta, care generează graficele. Aceasta este o bibliotecă externă.













