public TrieNodePtr(TrieNodePtr parent, TrieNode childNode) : this(childNode) { leftChangeIndex = parent.leftChangeIndex; rightChangeIndex = parent.rightChangeIndex; numChanges = parent.numChanges; }
public TrieNodePtr(TrieNodePtr parent, TrieNode childNode, int newIndex) : this(childNode) { leftChangeIndex = parent.numChanges == 0 ? newIndex : parent.leftChangeIndex; rightChangeIndex = newIndex; numChanges = parent.numChanges + 1; }
//Given text, find out what words match starting from startIdx public void parseText(string text, out List<WordMatch> matches, int startIdx = 0) { matches = new List<WordMatch>(10); List<TrieNodePtr> listPtrs = new List<TrieNodePtr>(); TrieNodePtr root = new TrieNodePtr(this); listPtrs.Add(root); //Start from the root node and walk down text, we maintain a list //because we can change 1 character every TrieNode.minDistance for (int cIdx = startIdx; cIdx < text.Length; ++cIdx) { char c = text[cIdx]; int cInt = (int)c - aInt; TrieNodePtr.doMatch(cIdx - startIdx, cInt, ref listPtrs, matches); if (listPtrs.Count == 0) { return; } } }
public static void doMatch(int cIdx, int cInt, ref List<TrieNodePtr> list, List<WordMatch> matches) { List<TrieNodePtr> newList = new List<TrieNodePtr>(); Logger.LogTrace("doMatch cIdx: {} char: {} list size {} matches size {}", cIdx, (char)(cInt + (int)'a'), list.Count, matches.Count); foreach (TrieNodePtr nodePtr in list) { //Found a direct match if (nodePtr.node.children[cInt] != null) { TrieNodePtr newNp = new TrieNodePtr(nodePtr, nodePtr.node.children[cInt]); newList.Add(newNp); newNp.addMatches(matches); } //If last change > 5, then add the rest of the children if (nodePtr.numChanges == 0 || cIdx - nodePtr.rightChangeIndex >= minDistance) { foreach (var x in nodePtr.node.childrenList) { int charInt = x.Item1; TrieNode childNode = x.Item2; //Ignore direct match, was taken care of above if (charInt == cInt) continue; TrieNodePtr newNp = new TrieNodePtr(nodePtr, childNode, cIdx); newList.Add(newNp); newNp.addMatches(matches); } } } list = newList; }