我修改了代碼this article from Visual Studio Magazine,它實現了Trie
。
下面的程序演示如何使用Trie
做快速前綴搜索。
爲了運行這個程序,你需要所謂的「words.txt」文字的大名單的文本文件。You can download one from Github here。
編譯完程序後,將「words.txt」文件複製到與可執行文件相同的文件夾中。
當您運行程序時,鍵入一個前綴(如prefix
;))並按return
,它會列出以該前綴開頭的所有單詞。
這應該是一個非常快速的查找 - 請參閱Visual Studio Magazine文章以獲取更多詳細信息!
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace ConsoleApp1
{
class Program
{
static void Main()
{
var trie = new Trie();
trie.InsertRange(File.ReadLines("words.txt"));
Console.WriteLine("Type a prefix and press return.");
while (true)
{
string prefix = Console.ReadLine();
if (string.IsNullOrEmpty(prefix))
continue;
var node = trie.Prefix(prefix);
if (node.Depth == prefix.Length)
{
foreach (var suffix in suffixes(node))
Console.WriteLine(prefix + suffix);
}
else
{
Console.WriteLine("Prefix not found.");
}
Console.WriteLine();
}
}
static IEnumerable<string> suffixes(Node parent)
{
var sb = new StringBuilder();
return suffixes(parent, sb).Select(suffix => suffix.TrimEnd('$'));
}
static IEnumerable<string> suffixes(Node parent, StringBuilder current)
{
if (parent.IsLeaf())
{
yield return current.ToString();
}
else
{
foreach (var child in parent.Children)
{
current.Append(child.Value);
foreach (var value in suffixes(child, current))
yield return value;
--current.Length;
}
}
}
}
public class Node
{
public char Value { get; set; }
public List<Node> Children { get; set; }
public Node Parent { get; set; }
public int Depth { get; set; }
public Node(char value, int depth, Node parent)
{
Value = value;
Children = new List<Node>();
Depth = depth;
Parent = parent;
}
public bool IsLeaf()
{
return Children.Count == 0;
}
public Node FindChildNode(char c)
{
return Children.FirstOrDefault(child => child.Value == c);
}
public void DeleteChildNode(char c)
{
for (var i = 0; i < Children.Count; i++)
if (Children[i].Value == c)
Children.RemoveAt(i);
}
}
public class Trie
{
readonly Node _root;
public Trie()
{
_root = new Node('^', 0, null);
}
public Node Prefix(string s)
{
var currentNode = _root;
var result = currentNode;
foreach (var c in s)
{
currentNode = currentNode.FindChildNode(c);
if (currentNode == null)
break;
result = currentNode;
}
return result;
}
public bool Search(string s)
{
var prefix = Prefix(s);
return prefix.Depth == s.Length && prefix.FindChildNode('$') != null;
}
public void InsertRange(IEnumerable<string> items)
{
foreach (string item in items)
Insert(item);
}
public void Insert(string s)
{
var commonPrefix = Prefix(s);
var current = commonPrefix;
for (var i = current.Depth; i < s.Length; i++)
{
var newNode = new Node(s[i], current.Depth + 1, current);
current.Children.Add(newNode);
current = newNode;
}
current.Children.Add(new Node('$', current.Depth + 1, current));
}
public void Delete(string s)
{
if (!Search(s))
return;
var node = Prefix(s).FindChildNode('$');
while (node.IsLeaf())
{
var parent = node.Parent;
parent.DeleteChildNode(node.Value);
node = parent;
}
}
}
}
所以你想找到一個集合中的所有字符串,使得你的輸入字符串是它們的前綴?你應該看看[String.startsWith](https://msdn.microsoft.com/en-us/library/bb383988.aspx)。你也應該自己嘗試一下,我們會指出錯誤,並從那裏引導你。 – hnefatl
你將不得不更具體一些......你可以發佈一些代碼來顯示你到目前爲止的內容嗎?並更準確地說明你的意思。 –
如果我懷疑您正在進行增量搜索,那麼您可能需要查看「Trie」數據結構。這可以非常快速地發現集合中以指定前綴開頭的所有字符串。有關詳細信息,請參見[此Visual Studio雜誌文章](https://visualstudiomagazine.com/articles/2015/10/20/text-pattern-search-trie-class-net.aspx)。 –