public override void Add(char[] word, int start) { 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 bucket. target = new BurstCacheBucket(); _next[c] = target; } else if (target.ShouldBurst) // else OK because there's never any need to burst a brand new bucket { target = BurstThisBucket(target); _next[c] = target; } target.Add(word, start + 1); }
BurstTrieNode BurstThisBucket(BurstNavigable bucketIn) { BurstCacheBucket bucket = (BurstCacheBucket)bucketIn; BurstTrieNode node = new BurstTrieNode { _next = new BurstNavigable[TRIE_WIDTH], End = bucket.End }; // node.me = key; // debug only // TODO maybe make this a higher performance construct? foreach (ArraySegment <char> item in bucket) { if (item.Count == 1) // in this case the suffix is consumed by the new trie node + entry (empty destination bucket, maybe, or now creating and adding to) { if (node._next[(int)item.Array[item.Offset]] == null) { BurstCacheBucket emptyBucket = new BurstCacheBucket(); emptyBucket.End = true; node._next[(int)item.Array[item.Offset]] = emptyBucket; // only needed if it was not there, so maybe save this assignment continue; } else // already a bucket there, from previous iteration in this loop { BurstCacheBucket reusingBucket = (BurstCacheBucket)node._next[(int)item.Array[item.Offset]]; reusingBucket.End = true; continue; } } else // there is more suffix that's not consumed by the new trie node + entry, so create / fill bucket { BurstNavigable nav = node._next[(int)item.Array[item.Offset]]; if (nav == null) { BurstCacheBucket newBucket = new BurstCacheBucket(); char[] arr = item.Array; int offset = item.Offset; newBucket.Add(arr, offset + 1, item.Count - 1); node._next[(int)arr[offset]] = newBucket; } else { ((BurstCacheBucket)nav).Add(item.Array, item.Offset + 1, item.Count - 1); } } } return(node); }
public override bool IsPresent(char[] word, int start) { if (word.Length == start) { return(End); } if (_next == null) { return(false); // there's no further to look! } BurstNavigable target = _next[word[start]]; if (target == null) { return(false); // no potentially matching suffix } return(target.IsPresent(word, start + 1)); // 1 = me.Length }
/// <summary> /// Exports the whole trie into the supplied list. /// </summary> public override void Reconstruct(char[] trail, int length, List <string> pile) { if (_next == null) { pile.Add(new string(trail, 0, length)); // end of trail. build string and Add to pile. return; } if (End) { pile.Add(new string(trail, 0, length)); } for (int i = MINIMAL_WIDTH_USE; i < MAXIMAL_WIDTH_USE; i++) // TODO: optimize by holding onto minimum, maximum values actually used in this node { BurstNavigable node = _next[i]; if (node != null) { trail[length] = (char)i; node.Reconstruct(trail, length + 1, pile); } } }