Compare commits
4 Commits
9d03817f77
...
c5c261fc1b
Author | SHA1 | Date |
---|---|---|
|
c5c261fc1b | 3 months ago |
|
70684d140e | 3 months ago |
|
1878d31454 | 3 months ago |
|
0cea94de4d | 3 months ago |
@ -0,0 +1,87 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace ConsoleImprovements.Client {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A crude implementation of the trie data structure for fast lookups
|
||||||
|
/// </summary>
|
||||||
|
public class Trie {
|
||||||
|
private readonly Node _root = new Node() {
|
||||||
|
Children = new Dictionary<char, Node>()
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a new string entry to the structure
|
||||||
|
/// </summary>
|
||||||
|
public void AddEntry(string str) {
|
||||||
|
Node current = _root;
|
||||||
|
foreach (char ch in str.ToLower()) {
|
||||||
|
if (!current.Children.TryGetValue(ch, out Node? next)) {
|
||||||
|
next = new Node();
|
||||||
|
current.Children[ch] = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
current.End = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Look up how the given string may continue
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="prefix">The string to base the search on</param>
|
||||||
|
/// <param name="node">outputs the reached node which is either an end node or has multiple children</param>
|
||||||
|
/// <returns>Continuation of the prefix (including the prefix)</returns>
|
||||||
|
public string? LookupNext(string prefix, out Node? node) {
|
||||||
|
string lowercase = prefix.ToLower();
|
||||||
|
Node current = _root;
|
||||||
|
foreach (char ch in lowercase) {
|
||||||
|
if (!current.Children.TryGetValue(ch, out Node? next)) {
|
||||||
|
node = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
var commonBuilder = new StringBuilder(lowercase);
|
||||||
|
while (current.Children.Count == 1) {
|
||||||
|
if (current.End) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyValuePair<char, Node> single = current.Children.First();
|
||||||
|
commonBuilder.Append(single.Key);
|
||||||
|
current = single.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = current;
|
||||||
|
return commonBuilder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Node {
|
||||||
|
public bool End;
|
||||||
|
public Dictionary<char, Node> Children = new Dictionary<char, Node>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all possible strings that can be made from the children of this node
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="prefix">Pass in the previously obtained string path to this node</param>
|
||||||
|
public List<string> CollectChildren(string prefix) {
|
||||||
|
var collected = new List<string>();
|
||||||
|
if (End) {
|
||||||
|
collected.Add(prefix.ToLower());
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ((char ch, Node node) in Children) {
|
||||||
|
collected.AddRange(node.CollectChildren(prefix + ch));
|
||||||
|
}
|
||||||
|
|
||||||
|
return collected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue