/// <summary> /// Finds the longest common prefix of the specified key. Sets values of /// <see cref="confluxState"/>, <see cref="lastState"/>, <see cref="prefixPath"/> and <see cref="prefixLenght"/>. /// <see cref="confluxState"/> gets the first conflux state encountered (null if no such state exists). /// <see cref="lastState"/> gets the last state encountered (null if no prefix exists). /// <see cref="prefixPath"/> gets the values of the states encountered. /// <see cref="prefixLenght"/> gets the lenght of longest common prefix (0 if no prefix exists). /// </summary> /// <param name="key">The key to search longest common preifix of.</param> protected void CommonPrefix(IEnumerable <TKey> key) { prefixLenght = 0; lastState = instance.Root; confluxState = null; var confluxFound = false; prefixPath = new Stack <IDawgNode <TKey, TValue> >(); foreach (var k in key) { //prefix can be continued if (lastState.Contains(k)) { lastState = lastState.Get(k); prefixPath.Push(lastState); //increment prefix lenght prefixLenght++; if (!confluxFound) //if conflux state was not found yet { //if lastState is conflux if (lastState.Children.Count() > 1) { confluxFound = true; confluxState = lastState; } } } else { break; } } }
public bool this[IDawgNode <TKey, TValue> state] { get { return(registred.ContainsKey(state) && registred[state]); } set { if (value) { if (!registred.ContainsKey(state)) { registred.Add(state, true); } else { registred[state] = true; } } else { if (registred.ContainsKey(state)) { registred.Remove(state); } } } }
IEnumerable <KeyValuePair <IEnumerable <TKey>, TValue> > Traverse(IDawgNode <TKey, TValue> node, IList <TKey> currentKey) { while (true) { if (Root != node) { //append node key currentKey.Add(node.Key); //if node has value then return new pair if (node.HasValue) { yield return(new KeyValuePair <IEnumerable <TKey>, TValue>(currentKey, node.Value)); } } if (node.LeftChild != null) { foreach (var child in Traverse(node.LeftChild, currentKey)) { yield return(child); } } currentKey.RemoveAt(currentKey.Count - 1); if (node.RightSibling != null) { node = node.RightSibling; continue; } break; } }
protected override void ReplaceOrRegister(IDawgNode <TKey, TValue> state) { var child = state.Children.Last(); //last child if (!Registered[child]) { //if child has children if (child.Children.Any()) { ReplaceOrRegister(child); } //if such q exist that q is in registry and q == child if (registry.ContainsKey(child)) { //not registered state is replaced by equal registred one //replacement is reference replacement //states are equal, but in .Net world they are different objects state.Remove(child.Key); state.Add(registry[child]); } else { //else this state becomes the registred one, //meaning that it may be used later as a replacement registry.Add(child, child); Registered[child] = true; } } }
protected AbstractDacukBuilder() { registry = new Dictionary <IDawgNode <TKey, TValue>, IDawgNode <TKey, TValue> >(); instance = new Dawg <TKey, TValue>(); confluxState = null; lastState = null; comparer = null; prefixLenght = 0; prefixPath = new Stack <IDawgNode <TKey, TValue> >(); Registered = new RegisteredPropertyHandler(); }
/// <summary> /// Adds the specified node. /// </summary> /// <param name="node">The node.</param> /// <exception cref="DawgException">When the specified node already exists.</exception> public void Add(IDawgNode <TKey, TValue> node) { if (LeftChild == null) { LeftChild = node; } else { var current = LeftChild; if (node.Key.CompareTo(current.Key) < 0) { node.RightSibling = LeftChild; LeftChild = node; } else { if (LeftChild.Key.CompareTo(node.Key) == 0) { throw new DawgException("The specified key already exists."); } var prev = current; current = current.RightSibling; if (current == null) { prev.RightSibling = node; } else { while (current != null && node.Key.CompareTo(current.Key) <= 0) { if (current.Key.CompareTo(node.Key) == 0) { throw new DawgException("The specified key already exists."); } prev = current; current = current.RightSibling; } node.RightSibling = current; prev.RightSibling = node; } } } }
/// <summary> /// Initializes a new instance of the <see cref="T:System.Object"/> class. /// </summary> public EndLinkedDawgNode(TKey key, IDawgNode <TKey, TValue> leftChild, IDawgNode <TKey, TValue> rightSibling, TValue value) : base(key, leftChild, rightSibling) { this.value = value; }
/// <summary> /// Initializes a new instance of the <see cref="T:System.Object"/> class. /// </summary> public EndLinkedDawgNode(TKey key, IDawgNode <TKey, TValue> leftChild, IDawgNode <TKey, TValue> rightSibling) : base(key, leftChild, rightSibling) { }
/// <summary> /// Replaces or registers newly created state. /// </summary> /// <param name="state">The state.</param> protected abstract void ReplaceOrRegister(IDawgNode <TKey, TValue> state);
/// <summary> /// Returns a hash code for the specified object. /// </summary> /// <returns> /// A hash code for the specified object. /// </returns> /// <param name="obj">The <see cref="T:System.Object"/> for which a hash code is to be returned.</param><exception cref="T:System.ArgumentNullException">The type of <paramref name="obj"/> is a reference type and <paramref name="obj"/> is null.</exception> public int GetHashCode(IDawgNode <TKey, TValue> obj) { return(EqualityComparer <object> .Default.GetHashCode(obj)); }
/// <summary> /// Determines whether the specified objects are equal. /// </summary> /// <returns> /// true if the specified objects are equal; otherwise, false. /// </returns> /// <param name="x">The first object of type <paramref name="T"/> to compare. /// </param><param name="y">The second object of type <paramref name="T"/> to compare.</param> public bool Equals(IDawgNode <TKey, TValue> x, IDawgNode <TKey, TValue> y) { return(ReferenceEquals(x, y)); }
/// <summary> /// Initializes a new instance of the <see cref="T:System.Object"/> class. /// </summary> public InnerDawgNode(TKey key, IDawgNode <TKey, TValue> leftChild, IDawgNode <TKey, TValue> rightSibling) { Key = key; LeftChild = leftChild; RightSibling = rightSibling; }
internal Dawg(IDawgNode <TKey, TValue> root) { this.Root = root; }
protected IEnumerable <KeyValuePair <IEnumerable <TKey>, TValue> > FuzzySearch(IDawgNode <TKey, TValue> node, List <TKey> currentKey, int currentDiff, int maxDiff, TKey[] key, int keyIndex) { if (currentDiff <= maxDiff) { if (Root != node) { //append node key currentKey.Add(node.Key); //if node has value then return new pair if (node.HasValue) { yield return(new KeyValuePair <IEnumerable <TKey>, TValue>(currentKey, node.Value)); } } if (node.LeftChild != null) { foreach (var child in FuzzySearch(node.LeftChild, currentKey, currentDiff + ((keyIndex >= key.Length || key[keyIndex].CompareTo(node.LeftChild.Key) != 0)? 1 : 0), maxDiff, key, keyIndex + 1)) { yield return(child); } } currentKey.RemoveAt(currentKey.Count - 1); if (node.RightSibling != null) { foreach (var child in FuzzySearch(node.RightSibling, currentKey, currentDiff + ((keyIndex >= key.Length || key[keyIndex].CompareTo(node.RightSibling.Key) != 0) ? 1 : 0), maxDiff, key, keyIndex + 1)) { yield return(child); } } } }