/// <summary> /// an attempt to do the forwardonlycursor alg using a stack instead of a queue. is slightly slower. not /// the tightest implementation either. /// </summary> /// <param name="trie"></param> /// <param name="text"></param> /// <returns></returns> public static List <StringSearchMatch> FindMatchesUsingForwardOnlyCursor2(ITrieStructure trie, string text) { List <StringSearchMatch> rv = new List <StringSearchMatch>(); if (string.IsNullOrEmpty(text)) { return(rv); } var maxIndex = text.Length - 1; Stack <MatchUoW> bucket = new Stack <MatchUoW>(); int bucketSize = 0; for (int i = 0; i <= maxIndex; i++) { //get current char char currentChar = text[i]; //1. set up new items Stack <MatchUoW> newItems = new Stack <MatchUoW>(); var node = trie.Root[currentChar]; if (node != null) { MatchUoW uow = new MatchUoW(i, currentChar, node); newItems.Push(uow); } //2. handle old items for (int j = 0; j < bucketSize; j++) { var eachOld = bucket.Pop(); //if this matches, update the rv var match = eachOld.GetWordMatch(); if (match != null) { rv.Add(match); } //can we carry the item over? if (eachOld.MoveNext(currentChar)) { newItems.Push(eachOld); } } bucketSize = newItems.Count; for (int j = 0; j < bucketSize; j++) { bucket.Push(newItems.Pop()); } } return(rv); }
public static List<StringSearchMatch> FindMatchesUsingForwardOnlyCursor2a(ITrieStructure trie, string text) { List<StringSearchMatch> rv = new List<StringSearchMatch>(); if (string.IsNullOrEmpty(text)) return rv; var maxIndex = text.Length - 1; Queue<MatchUoW> queue = new Queue<MatchUoW>(); for (int i = 0; i <= maxIndex; i++) { //get current char char currentChar = text[i]; //dequeue all carryover items, and identify which ones can continue Queue<MatchUoW> reQueuedItems = new Queue<MatchUoW>(); int queueCount = queue.Count; if (queueCount > 0) { for (int j = 0; j < queueCount; j++) { MatchUoW dequeueItem = queue.Dequeue(); //if this matches, update the rv var match = dequeueItem.GetWordMatch(); if (match != null) rv.Add(match); //can we carry the item over? if (dequeueItem.MoveNext(currentChar)) { reQueuedItems.Enqueue(dequeueItem); } } //queue up the ones that continue foreach (var each in reQueuedItems) queue.Enqueue(each); } //Possibly create a unit of work for this particular character (starting from root) var node = trie.Root[currentChar]; if (node == null) continue; MatchUoW uow = new MatchUoW(i, currentChar, node); queue.Enqueue(uow); } return rv; }
/// <summary> /// for the provided index position, examines the trie to see if it can handle the character, and moves through /// the trie graph until it no longer matches. returns list to account for situation where matches share a common suffix. /// </summary> /// <param name="trie"></param> /// <param name="idx"></param> /// <param name="text"></param> /// <param name="graspLengthOUT">the number of characters processed</param> /// <returns></returns> public static List<StringSearchMatch> FindMatchesAtPosition(ITrieStructure trie, int idx, string text, out int graspLengthOUT) { List<StringSearchMatch> rv = new List<StringSearchMatch>(); graspLengthOUT = 0; //basic cursor position validation int maxIndex = text.Length - 1; if (maxIndex < idx) return rv; graspLengthOUT = 1;//we're at least processing 1 character var currentIdx = idx; var currentNode = trie.Root; var currentChar = text[currentIdx]; //do the first test in the loop currentNode = currentNode[currentChar]; if (currentNode == null) return rv; var queue = new Queue<Tuple<int, char, ITrieNode>>(); //define function to increment position, and update currentIdx, currentChar, and queue it up //implicit is the currentNode position has ALREADY been incremented at this point Func<bool> enqueue = () => { //get the next char currentIdx++; //validate position if (maxIndex < currentIdx) return false; currentChar = text[currentIdx]; queue.Enqueue(new Tuple<int, char, ITrieNode>(currentIdx, currentChar, currentNode)); return true; }; enqueue(); while (queue.Count > 0) { var tuple = queue.Dequeue(); currentNode = tuple.Item3; currentChar = tuple.Item2; currentIdx = tuple.Item1; //if we're matching, return it if (currentNode.HasWord) { var match = StringSearchMatch.New(currentIdx - 1 - currentNode.Id.Length, currentNode.Id, currentNode.Value); rv.Add(match); //update grasp length var matchGraspLength = match.Word.Length; if (graspLengthOUT < matchGraspLength) graspLengthOUT = matchGraspLength; } //does the trie even handle (aka lift, bro) this particular character? currentNode = currentNode[currentChar]; if (currentNode != null) { enqueue(); } } return rv; }
/// <summary> /// an attempt to do the forwardonlycursor alg using a stack instead of a queue. is slightly slower. not /// the tightest implementation either. /// </summary> /// <param name="trie"></param> /// <param name="text"></param> /// <returns></returns> public static List<StringSearchMatch> FindMatchesUsingForwardOnlyCursor2(ITrieStructure trie, string text) { List<StringSearchMatch> rv = new List<StringSearchMatch>(); if (string.IsNullOrEmpty(text)) return rv; var maxIndex = text.Length - 1; Stack<MatchUoW> bucket = new Stack<MatchUoW>(); int bucketSize = 0; for (int i = 0; i <= maxIndex; i++) { //get current char char currentChar = text[i]; //1. set up new items Stack<MatchUoW> newItems = new Stack<MatchUoW>(); var node = trie.Root[currentChar]; if (node != null) { MatchUoW uow = new MatchUoW(i, currentChar, node); newItems.Push(uow); } //2. handle old items for (int j = 0; j < bucketSize; j++) { var eachOld = bucket.Pop(); //if this matches, update the rv var match = eachOld.GetWordMatch(); if (match != null) rv.Add(match); //can we carry the item over? if (eachOld.MoveNext(currentChar)) { newItems.Push(eachOld); } } bucketSize = newItems.Count; for (int j = 0; j < bucketSize; j++) { bucket.Push(newItems.Pop()); } } return rv; }
public static List <StringSearchMatch> FindMatchesUsingForwardOnlyCursor2a(ITrieStructure trie, string text) { List <StringSearchMatch> rv = new List <StringSearchMatch>(); if (string.IsNullOrEmpty(text)) { return(rv); } var maxIndex = text.Length - 1; Queue <MatchUoW> queue = new Queue <MatchUoW>(); for (int i = 0; i <= maxIndex; i++) { //get current char char currentChar = text[i]; //dequeue all carryover items, and identify which ones can continue Queue <MatchUoW> reQueuedItems = new Queue <MatchUoW>(); int queueCount = queue.Count; if (queueCount > 0) { for (int j = 0; j < queueCount; j++) { MatchUoW dequeueItem = queue.Dequeue(); //if this matches, update the rv var match = dequeueItem.GetWordMatch(); if (match != null) { rv.Add(match); } //can we carry the item over? if (dequeueItem.MoveNext(currentChar)) { reQueuedItems.Enqueue(dequeueItem); } } //queue up the ones that continue foreach (var each in reQueuedItems) { queue.Enqueue(each); } } //Possibly create a unit of work for this particular character (starting from root) var node = trie.Root[currentChar]; if (node == null) { continue; } MatchUoW uow = new MatchUoW(i, currentChar, node); queue.Enqueue(uow); } return(rv); }
/// <summary> /// for the provided index position, examines the trie to see if it can handle the character, and moves through /// the trie graph until it no longer matches. returns list to account for situation where matches share a common suffix. /// </summary> /// <param name="trie"></param> /// <param name="idx"></param> /// <param name="text"></param> /// <param name="graspLengthOUT">the number of characters processed</param> /// <returns></returns> public static List <StringSearchMatch> FindMatchesAtPosition(ITrieStructure trie, int idx, string text, out int graspLengthOUT) { List <StringSearchMatch> rv = new List <StringSearchMatch>(); graspLengthOUT = 0; //basic cursor position validation int maxIndex = text.Length - 1; if (maxIndex < idx) { return(rv); } graspLengthOUT = 1;//we're at least processing 1 character var currentIdx = idx; var currentNode = trie.Root; var currentChar = text[currentIdx]; //do the first test in the loop currentNode = currentNode[currentChar]; if (currentNode == null) { return(rv); } var queue = new Queue <Tuple <int, char, ITrieNode> >(); //define function to increment position, and update currentIdx, currentChar, and queue it up //implicit is the currentNode position has ALREADY been incremented at this point Func <bool> enqueue = () => { //get the next char currentIdx++; //validate position if (maxIndex < currentIdx) { return(false); } currentChar = text[currentIdx]; queue.Enqueue(new Tuple <int, char, ITrieNode>(currentIdx, currentChar, currentNode)); return(true); }; enqueue(); while (queue.Count > 0) { var tuple = queue.Dequeue(); currentNode = tuple.Item3; currentChar = tuple.Item2; currentIdx = tuple.Item1; //if we're matching, return it if (currentNode.HasWord) { var match = StringSearchMatch.New(currentIdx - 1 - currentNode.Id.Length, currentNode.Id, currentNode.Value); rv.Add(match); //update grasp length var matchGraspLength = match.Word.Length; if (graspLengthOUT < matchGraspLength) { graspLengthOUT = matchGraspLength; } } //does the trie even handle (aka lift, bro) this particular character? currentNode = currentNode[currentChar]; if (currentNode != null) { enqueue(); } } return(rv); }