Zajímalo nejvíce ÚČINNÁ způsob, jak vytvořit strom binárního vyhledávání na kontrolu pravopisu tím, že čte řekněme 1000 slovo soubor slovníku a pak mít to vyzkoušet jiný dokument, který říci má několik odstavců.
Použití binární vyhledávací strom jako kontrola pravopisu
ternární strom trie by bylo účinnější
Pokud potřebujete udělat auto naznačují / prefix vyhledávání stejně, pak Patricia strom nebo radix stromu je dívat.
S příkladem jsi dal, výkon je pravděpodobné, že bude irelevantní, protože v počítači celá operace bude trvat přibližně 1% času to bere uživateli přečíst první výsledek, který ukázat, pokud nechcete používat zcela stupidní algoritmus , Ale přesto, budu předpokládat, že problém je dostatečně velká, že výkon je problém.
Je-li slovník soubor předtříděné (jako většina z nich), a v případě, že text je malý ve srovnání s slovníku, jak byste popsat, pak bych být v pokušení, aby třídit text, možná odstranění duplicit, a pak iterovat obou seznamech side-by -side stejným postupem jako sloučení druhu, kromě toho, uvést, zda všechna znění slovo ve slovníku místo výstupu sloučené seznam.
To dělá práci v asi M log M srovnáními za druhu, navíc ve většině srovnání N + M pro iteraci, (možná méně, ale ne složitost-less). To je docela blízko k optimálnímu složitosti pro provoz jednorázovým: zbavit lineárního výrazu v N budete muset najít způsob, jak to číst celý slovník z disku vůbec. Jsem si jistý, že je možné bsearch do souboru, a to zejména vzhledem k tomu, že slova jsou poměrně krátké, ale pro malé N je to jen dohadovat, zda hledá kolem místa bude skutečně rychlejší než sériově přístupu k datům.
To má následující vlastnosti:
- Nemusíte držet slovníku v paměti, pouze text.
- Nicméně, stačí pouze provést jeden průchod přes souboru slovníku.
- Nemusíte dělat žádné drahé zpracování slovníku.
Samozřejmě, pokud není předem roztříděné soubor slovníku pak to nebude fungovat, a pokud můžete držet slovníku vysedáváním v paměti pro další operaci pravopisu pak můžete amortizovat náklady na I / O a zpracování do strom přes několik různých textů, které bude výhra v dlouhodobém horizontu.
Je-li slovník je opravdu obrovská, pak byste měli mít prospěch z jejich ukládání na disk v předem zpracované formě, která odpovídá nevyvážené stromu vážené podle relativních četností jednotlivých slov v češtině. Pak můžete udělat méně než O (N) přístup k disku malých textů, a na většině OS neobtěžoval načtením do paměti vůbec, jen mmap soubor a nechat OS starosti. Pro velký slovník, celý klastry obsahující slova začínající „dimethyl“ nemusí být nikdy nedotkl.
Dalším aspektem je splay strom pro slovníku. Rozevírá strom nerovnováhy sama, jak se díváte, co se v ní tak, aby často používané hodnoty rychleji najít. Most textu opakovaně používá malý počet slov, takže v případě, že text je dostatečně dlouhá, aby ospravedlnit režijní to vyhraje nakonec.
Oba výše zmíněné údaje jsou předmětem Steven A Lowe názoru, že pro smyčce, je trie bije normální strom. Nevím, jestli najdete off-the-police rozevírá Trie, ačkoli.
Pokud jste jen snaží zjistit, zda existuje konkrétní slovo ve slovníku (to znamená, že je napsána správně), pak si nemyslím, binární vyhledávací strom, je to, co jste po. Lepší způsob, jak uchovávat tyto informace by se ve stromu stylu, kde každý následující uzel na stromě je jeden znak, a čtení cestu ke koncovému uzlu vám pravopis tohoto slova. Byste také potřeba přidat značku k označení slovo-konec.
Např: že váš slovník má tato slova: auto, vozík, kočka, pohár, střih
- C
- A
- R
- end
- T
- T
- end
- U
- P
- end
- T
- end
Kontrola, zda existuje slovo je otázka pohledu na každé písmeno individuálně, a že existuje děti aktuálního uzlu.
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.
Jak budete ukládat tyto informace je jen na vás. Jako Steven poukázal, je Ternární Search Trie může být způsob, jak jít: každý uzel bude mít 27 možných podřízené uzly.
Jste mrtvý nastavit na používání binární vyhledávací strom? Bloom filtr by pravděpodobně efektivnější datová struktura.
Vidět, že se jedná o domácí otázka, budu předpokládat, že budete muset použít obyčejný starý binární strom (ne červeno-černé stromy, AVL stromy, Radix stromy, atd.) Odpověď pak je pokusit se udržet strom vyvážený, jak si ho postavit ze seznamu slov. Jedním z přístupů je náhodně seznamu před čtením ji, to dává rozumné výsledky. Ale můžete získat lepší výsledky, pokud si objednáte vstupní posloupnost (pomocí stejné porovnání jako to, co strom používá), potom rekurzivně rozdělit vstup vrací střed, dokud žádné prvky zůstávají. Výsledkem je vyvážený strom.
Zaklepal jsem tři různé způsoby, jak to udělat v 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);
}
Tato stránka by vám měl pomoci, že má implementace v Javě.
Jako předpokládány trie by účinnější než binární strom, ale můžete použít HashMap a hash každé slovo. Máte malou slovník (1000 záznamů). Jak jste si projít svůj dokument, zkontrolujte, zda jsou slova v HashMap. V případě, že nejste, slovo je Předpokládá se, že chybně.
To vám nedá možnou opravu chybně napsané slovo. To jen vám řekne ano nebo ne (správné, nebo ne).
Pokud chcete, pravopisné návrhy pro nesprávné slov můžete spustit ze slova v souboru, pak generovat všechna slova 1 upravit opodál a přidejte je jako děti z původního slova. Tímto způsobem si vytváříte graf. Jet 2 úrovně hluboké pro maximální rychlost vs přesnost. Máte-li generovat textový uzel, který je ve slovníku, můžete jej přidat do seznamu možných návrhů. Na konci, vrátí seznam možných návrhů.
Pro lepší kontrolu pravopisu, se také pokusit přidat fonetický párování.
sea jo -> viz yah
Tento způsob (vytváření grafů řetězců 1 upravit daleko), je „pomalu“. Ale je to dobré akademické cvičení. Runtime je O (n ^ větve).
V případě zájmu je zde odkaz na jednu jsem stavěl sám (pro zábavu): https://github.com/eamocanu/spellcheck.graph
Některé ukázkové grafy: https://github.com/eamocanu/spellcheck.graph/tree/master/graph%20photos
Také jsem přidal UI komponent na to, které vytváří grafy. Jedná se o externí knihovnu.













