public void TrieConstructorTest() { Trie <TrieElement> trie = new Trie <TrieElement>(); Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("VLUnitTests.Resources.TrieTest.txt"); string text = stream.ReadAll(); // read all data from testing file // add "references" that will be searched trie.Add("id.aliquam.lorem"); trie.Add("a.b.c.d"); trie.Add("x.y"); trie.Add("eeee.eeee"); // complete building the trie trie.CreatePredecessorsAndShortcuts(); TrieElement e = trie.Root; List <string> foundWords = new List <string>(); // create list of expeced results List <string> expectedWords = new List <string>(); expectedWords.Add("id.aliquam.lorem"); expectedWords.Add("id.aliquam.lorem"); expectedWords.Add("eeee.eeee"); expectedWords.Add("id.aliquam.lorem"); expectedWords.Add("eeee.eeee"); expectedWords.Add("eeee.eeee"); expectedWords.Add("eeee.eeee"); expectedWords.Add("a.b.c.d"); expectedWords.Add("a.b.c.d"); expectedWords.Add("a.b.c.d"); expectedWords.Add("a.b.c.d"); expectedWords.Add("a.b.c.d"); // run the algorithm foreach (char c in text) { e = trie.Step(e, c); if (e.IsTerminal) { foundWords.Add(e.Word); } } // compare with expected if (foundWords.Count == expectedWords.Count) { bool ok = true; for (int i = 0; i < foundWords.Count; i++) { ok = ok && foundWords[i] == expectedWords[i]; } Assert.IsTrue(ok); } else { Assert.Fail("Found and expected words count don't match."); } }
private void Add(IList <T> key, IEnumerable <T> fullkey) { if (!key.Any()) { _children[new T[0]] = new TrieElement(fullkey, _comp); return; } bool included; var match = _children.FirstOrDefault(a => a.Key.StartsWith(key, _tokencomp), out included); if (included) { if (match.Key.CompareCount(key) != 0) { //we need to split an existing key _children.Remove(match.Key); var newchild = new Trie <T>(_comp, _tokencomp) { { new T[0], fullkey } }; newchild._children[match.Key.Slice(key.Count)] = match.Value; _children[key] = newchild; return; } // we add epsilon value var trie = match.Value as Trie <T>; trie?.Add(new T[0], fullkey); return; } match = _children.FirstOrDefault(a => a.Key.Any() && key.StartsWith(a.Key, _tokencomp), out included); if (included) { //we need to split this key var trie = match.Value as Trie <T>; if (trie == null) { _children.Remove(match); trie = new Trie <T>(_comp, _tokencomp) { { new T[0], match.Value.First() } }; _children[match.Key] = trie; } trie.Add(key.Slice(match.Key.Count), fullkey); return; } var submatch = _children.Attach(a => a.Key.LongestCommonPrefix(key, _tokencomp)).FirstOrDefault(a => a.Item2.Any(), out included); if (included) { //we need to split both match = submatch.Item1; var prefix = submatch.Item2.Select(a => a.Item1).ToArray(); _children.Remove(match.Key); var newchild = new Trie <T>(_comp, _tokencomp) { { key.Slice(prefix.Length), fullkey } }; newchild._children[match.Key.Slice(prefix.Length)] = match.Value; _children[prefix] = newchild; return; } //we have no definitions for anything like this key this._children[key] = new TrieElement(fullkey, _comp); }