14

我已经对一个研究项目进行了基本搜索。我试图通过构建后缀树来提高搜索效率。我对Ukkonen算法的 C# 实现感兴趣。如果存在这样的实现,我不想浪费时间自己动手。

4

3 回答 3

12

难以回答的问题。这是我能找到的最接近的匹配:http: //www.codeproject.com/KB/recipes/ahocorasick.aspx,它是 Aho-Corasick 字符串匹配算法的实现。现在,该算法使用类似后缀树的结构:http ://en.wikipedia.org/wiki/Aho-Corasick_algorithm

现在,如果你想要一个前缀树,这篇文章声称为你提供了一个实现:http: //www.codeproject.com/KB/recipes/prefixtree.aspx

<幽默> 既然我做了你的功课,你修剪我的草坪怎么样。(参考: http: //flyingmoose.org/tolksarc/homework.htm)< /HUMOR >

编辑:我发现了一个 C# 后缀树实现,它是在博客上发布的 C++ 的一个端口: http ://code.google.com/p/csharsuffixtree/source/browse/#svn/trunk/suffixtree

编辑:Codeplex 有一个专注于后缀树的新项目:http: //suffixtree.codeplex.com/

于 2008-10-11T05:31:00.343 回答
5

嘿,刚刚完成了包含不同 trie 实现的 .NET (c#) 库。其中:

  • 经典特里
  • 帕特里夏特里
  • 后缀特里
  • 使用Ukkonen算法的 trie

我试图使源代码易于阅读。用法也很简单:

using Gma.DataStructures.StringSearch;

...

var trie = new UkkonenTrie<int>(3);
//var trie = new SuffixTrie<int>(3);

trie.Add("hello", 1);
trie.Add("world", 2);
trie.Add("hell", 3);

var result = trie.Retrieve("hel");

该库经过良好测试,并作为TrieNet NuGet 包发布。

github.com/gmamaladze/trienet

于 2017-09-27T14:46:00.420 回答
3

这是一个相当有效的后缀树的实现。我没有研究过 Ukkonen 的实现,但是我相信这个算法的运行时间是相当合理的,大约O(N Log N). 请注意,创建的树中的内部节点数等于父字符串中的字母数。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using NUnit.Framework;

namespace FunStuff
{
    public class SuffixTree
    {
        public class Node
        {
            public int Index = -1;
            public Dictionary<char, Node> Children = new Dictionary<char, Node>();
        }

        public Node Root = new Node();
        public String Text;

        public void InsertSuffix(string s, int from)
        {             
            var cur = Root;
            for (int i = from; i < s.Length; ++i)
            {
                var c = s[i];
                if (!cur.Children.ContainsKey(c))
                {
                    var n = new Node() {Index = from};
                    cur.Children.Add(c, n);

                    // Very slow assertion. 
                    Debug.Assert(Find(s.Substring(from)).Any());

                    return;
                }
                cur = cur.Children[c];
            }
            Debug.Assert(false, "It should never be possible to arrive at this case");
            throw new Exception("Suffix tree corruption");
        }

        private static IEnumerable<Node> VisitTree(Node n)
        {
            foreach (var n1 in n.Children.Values)
                foreach (var n2 in VisitTree(n1))
                    yield return n2;
            yield return n;
        }

        public IEnumerable<int> Find(string s)
        {
            var n = FindNode(s);
            if (n == null) yield break;
            foreach (var n2 in VisitTree(n))
                yield return n2.Index;
        }

        private Node FindNode(string s)
        {
            var cur = Root;
            for (int i = 0; i < s.Length; ++i)
            {
                var c = s[i];
                if (!cur.Children.ContainsKey(c))
                {
                    // We are at a leaf-node.
                    // What we do here is check to see if the rest of the string is at this location. 
                    for (var j=i; j < s.Length; ++j)
                        if (cur.Index + j >= Text.Length || Text[cur.Index + j] != s[j])
                            return null;
                    return cur;
                }
                cur = cur.Children[c];
            }
            return cur;
        }

        public SuffixTree(string s)
        {
            Text = s;
            for (var i = s.Length - 1; i >= 0; --i)
                InsertSuffix(s, i);
            Debug.Assert(VisitTree(Root).Count() - 1 == s.Length);
        }
    }

    [TestFixture]
    public class TestSuffixTree
    {
        [Test]
        public void TestBasics()
        {
            var s = "banana";
            var t = new SuffixTree(s);
            var results = t.Find("an").ToArray();
            Assert.AreEqual(2, results.Length);
            Assert.AreEqual(1, results[0]);
            Assert.AreEqual(3, results[1]);
        }
    } 
}
于 2013-09-13T13:47:28.070 回答