/// <summary> /// Add child node /// </summary> /// <param name="c">Letter</param> /// <param name="child">Node to add</param> /// <returns></returns> public bool AddChild(char c, TrieNode child) { Children.Add(c, child); return true; }
/// <summary> /// Basic Schulz and Mihov algoritm /// </summary> /// <returns>The correction nodes.</returns> /// <param name="typo">Typo.</param> /// <param name="start">Start.</param> /// <param name="editDistance">Edit distance.</param> /// <param name="includeOnlyWords">If set to <c>true</c> include only words.</param> IList<TrieNode> GetCorrectionNodes(string typo, TrieNode start, int editDistance, bool includeOnlyWords = true) { var corrections = new List<TrieNode> (); if (string.IsNullOrEmpty (typo)) { return corrections; } LevTAutomataImitation automata = new LevTAutomataImitation (typo, editDistance); Stack<SpellCheckerState> stack = new Stack<SpellCheckerState> (); stack.Push (new SpellCheckerState () { Node = start, AutomataState = 0, AutomataOffset = 0, }); while (stack.Count > 0) { SpellCheckerState state = stack.Pop(); automata.LoadState (state.AutomataState, state.AutomataOffset); AutomatonState nextZeroState = automata.GetNextState (0); foreach (char c in state.Node.Children.Keys) { AutomatonState nextState = null; if ((state.AutomataOffset < typo.Length && typo[state.AutomataOffset] == c) || (state.AutomataOffset < typo.Length - 1 && typo[state.AutomataOffset + 1] == c) || (state.AutomataOffset < typo.Length - 2 && typo[state.AutomataOffset + 2] == c)) { nextState = automata.GetNextState (automata.GetCharacteristicVector(c, state.AutomataOffset)); } else { nextState = nextZeroState; } if (nextState != null) { TrieNode nextNode = state.Node.Children [c]; if (nextNode.Children.Count > 0) { stack.Push (new SpellCheckerState () { Node = nextNode, AutomataState = nextState.State, AutomataOffset = nextState.Offset }); } if ((nextNode.IsWord || !includeOnlyWords) && automata.IsAcceptState (nextState.State, nextState.Offset)) { corrections.Add (nextNode); } } } } return corrections; }
public SpellCheckerState(TrieNode node, int state, int offset) { Node = node; AutomataState = state; AutomataOffset = offset; }
/// <summary> /// Find all words in dictionary such that Levenshtein distance to typo less or equal to editDistance /// </summary> /// <returns>Set of possible corrections</returns> /// <param name="typo">Garbled word.</param> /// <param name="start">Start search on this node</param> /// <param name="editDistance">Edit distance.</param> IEnumerable<string> GetCorrectionStrings(string typo, TrieNode start, int editDistance) { return GetCorrectionNodes (typo, start, editDistance).Select(x => x.Key); }