/// <summary> /// Add word into the container using a starting index /// </summary> /// <param name="word">char array word</param> /// <param name="start">starting index</param> /// <param name="pageCount">pagecount of that word</param> public override void Add(char[] word, int start, int pageCount) { if (word.Length == start) { End = true; return; } int c = (int)word[start]; if (_next == null) { _next = new BurstNavigable[TRIE_WIDTH]; } BurstNavigable target = _next[c]; if (target == null) { // always start with a container. target = new MyContainer(); _next[c] = target; } else if (target.ShouldBurst) // else OK because there's never any need to burst a brand new bucket { target = BurstThisContainer(target); _next[c] = target; } target.Add(word, start + 1, pageCount); }
/// <summary> /// Get 10 words from the current word /// </summary> /// <param name="temp">node or container</param> /// <param name="word">string based prefix</param> /// <returns>10 words from that prefix</returns> public List <string> GetWords(BurstNavigable temp, string word) { List <string> result = new List <string>(); GetWords(temp, word.ToCharArray(), result, 0, ""); return(result); }
/// <summary> /// Burst the container, replace it with a node and the most common character will be the child of that node /// anything left will be put in containers approriately /// </summary> /// <param name="temp">container</param> /// <returns>a node with an array of children that are either a node or container</returns> public MyTrieNode BurstThisContainer(BurstNavigable temp) { MyTrieNode node = new MyTrieNode(); IEnumerator <Word> _enumerator = temp.GetChildren().GetEnumerator(); while (_enumerator.MoveNext()) { node.Add(_enumerator.Current.content.ToCharArray(), 0, _enumerator.Current.pageCount); } return(node); }
/// <summary> /// Get words from the container or node. If node then we continue to traverse down, if not /// we will just add all the word in the container into the list /// </summary> /// <param name="temp">node or container</param> /// <param name="result">list of the words</param> /// <param name="resultString">result string to be concat with what is in the container</param> private void GetWords(BurstNavigable temp, List <string> result, string resultString) { if (result.Count >= 10) { return; } if (temp == null) { return; } else { if (temp.End) {//if end then add if (!result.Contains(resultString)) { result.Add(resultString); } } if (temp.getType() == 'n') //if node traverse every node in the children { BurstNavigable[] array = temp.GetNexts(); for (int i = 0; i < array.Length; i++) { GetWords(array[i], result, resultString + (char)i); } } else //if container, add into all the string inside the container { IEnumerator <Word> _enumerator = temp.GetChildren().GetEnumerator();; while (_enumerator.MoveNext()) { if (result.Count >= 10) { break; } if (!result.Contains(resultString + _enumerator.Current.content)) { result.Add(resultString + _enumerator.Current.content); } } } } }
/// <summary> /// Will get back all the suggestions that is the same length with the prefix and within 1,2 Levenshtein Distance /// </summary> /// <param name="temp">node or conatiner</param> /// <param name="result">list to store all the string</param> /// <param name="resultString">result string to be compared with prefix</param> /// <param name="prefix">word input by the user</param> /// <param name="limit">limit</param> /// <param name="start">starting index</param> private void GetSuggestionsWithLimits(BurstNavigable temp, List <string> result, string resultString, string prefix, int limit, int start) { if (temp == null) { return; } if (result.Count >= 10) { return; } if (start == limit) { int distance = CalcLevenshteinDistance(prefix, resultString); if (temp.End && (distance == 1 || distance == 2)) { if (!result.Contains(resultString)) { result.Add(resultString); } return; } if (distance == 1 || distance == 2) { if (result.Count < 10) { if (!result.Contains(resultString)) { result.Add(resultString); } } } return; } if (temp.getType() == 'n') //if node traverse every node in the children { BurstNavigable[] array = temp.GetNexts(); for (int i = 0; i < array.Length; i++) { GetSuggestionsWithLimits(array[i], result, resultString + (char)i, prefix, limit, start + 1); } } else //if container, add into all the string inside the container { IEnumerator <Word> _enumerator = temp.GetChildren().GetEnumerator();; while (_enumerator.MoveNext()) { if (result.Count >= 10) { break; } string left = ""; for (int i = start; i < limit && i < _enumerator.Current.content.Length; i++) { left = left + _enumerator.Current.content[i]; } resultString = resultString + left; int distance = CalcLevenshteinDistance(prefix, resultString); if (distance == 1 || distance == 2) { if (!result.Contains(resultString)) { result.Add(resultString); } } } } }
/// <summary> /// get all the prefix suggestion from the input word /// </summary> /// <param name="temp">node or container</param> /// <param name="word">character array of the word</param> /// <param name="result">result list</param> /// <param name="start">starting index</param> /// <param name="resultString">resulting string to be concat with what is left in the container before adding</param> private void GetWords(BurstNavigable temp, char[] word, List <string> result, int start, string resultString) { if (temp == null) { return; } if (start == word.Length) { //if this is a node, traverse through each node of the children to get all the children nodes if (temp.getType() == 'n') { if (temp.End) { if (!result.Contains(resultString)) { result.Add(resultString); } } if (result.Count >= 10) { return; } else { BurstNavigable[] array = temp.GetNexts(); for (int i = 0; i < array.Length; i++) { GetWords(array[i], result, resultString + (char)i); } } } else //if not just add all the words of the container into the list and return; { IEnumerator <Word> _enumerator = temp.GetChildren().GetEnumerator();; while (_enumerator.MoveNext()) { if (result.Count >= 10) { break; } if (!result.Contains(resultString + _enumerator.Current.content)) { result.Add(resultString + _enumerator.Current.content); } } } } else if (temp.getType() == 'n') { int c = (int)word[start]; temp = temp.GetChild(c); if (temp == null) { return; } GetWords(temp, word, result, start + 1, resultString + word[start]); } else { string left = ""; for (int i = start; i < word.Length; i++) { left = left + word[i]; } IEnumerator <Word> _enumerator = temp.GetChildren().GetEnumerator();; while (_enumerator.MoveNext()) { if (result.Count >= 10) { break; } if (_enumerator.Current.content.StartsWith(left)) { if (!result.Contains(resultString + _enumerator.Current.content)) { result.Add(resultString + _enumerator.Current.content); } } } } }