Ищете реализацию дерева суффиксов в C#?

Я реализовал базовый поиск исследовательского проекта. Я пытаюсь сделать поиск более эффективным, создав дерево суффиксов. Меня интересует реализация C# алгоритма Ukkonen. Я не хочу тратить время на создание собственного, если такая реализация существует.


person Goran    schedule 04.10.2008    source источник
comment
Можете ли вы вообще уточнить свой вопрос?   -  person Matt Hanson    schedule 11.10.2008
comment
Я пытаюсь реализовать поиск в рамках исследовательского проекта. Я реализовал обратный индекс и добавочное заполнение индекса. Затем я хотел сделать поиск еще более эффективным, но не хотел запускать свою собственную реализацию ST, если она существует.   -  person Goran    schedule 11.10.2008


Ответы (3)


Эй, только что закончил реализацию библиотеки .NET (c#), содержащей различные реализации 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.

person George Mamaladze    schedule 27.09.2017
comment
Спасибо за реализацию алгоритма Укконена. Отличная работа. - person Tomer Pintel; 14.12.2020

Тяжелый вопрос. Вот самое близкое совпадение, которое я смог найти: http://www.codeproject.com/KB/recipes/ahocorasick.aspx, который представляет собой реализацию алгоритма сопоставления строк Ахо-Корасика. Теперь алгоритм использует структуру, подобную суффиксному дереву, согласно: http://en.wikipedia.org/wiki/Aho-Corasick_algorithm

Теперь, если вам нужно дерево префиксов, в этой статье утверждается, что для вас есть реализация: http://www.codeproject.com/KB/recipes/prefixtree.aspx

ЮМОР> Теперь, когда я сделал твою домашнюю работу, как насчет того, чтобы постричь мою лужайку. (Ссылка: http://flyingmoose.org/tolksarc/homework.htm) ‹ /ЮМОР>

Правка: я нашел реализацию дерева суффиксов C#, которая была портом C++ и была опубликована в блоге: http://code.google.com/p/csharsuffixtree/source/просмотреть/#svn/trunk/suffixtree

Изменить. В Codeplex есть новый проект, посвященный деревьям суффиксов: http://suffixtree.codeplex.com/

person torial    schedule 11.10.2008
comment
Я ищу суффиксное дерево. - person Goran; 11.10.2008

Вот реализация дерева суффиксов, которая достаточно эффективна. Я не изучал реализацию Укконена, но время работы этого алгоритма я считаю вполне разумным, примерно 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]);
        }
    } 
}
person cdiggins    schedule 13.09.2013
comment
-@cdiggins, извините за мое невежество. Я впервые вижу класс в другом классе. В вашем коде public class Node находится внутри public class SuffixTree, в чем здесь заключается умение? - person ; 01.07.2014
comment
Я знаю, что этот пост устарел, но, похоже, с этим кодом возникла проблема при некоторых обстоятельствах, которые я не могу понять. Установите S = TAGGAAATTC и попробуйте t.Find(CTATT), и строка f (Text[cur.Index + j] != s[j]) приведет к исключению IndexOutsideBoundsOfArray. Ваша реализация кажется очень элегантной и достаточно эффективной (печатать Ukkoken немного... сложно). Я не могу найти способ обойти этот баг. - person Ilhan; 16.08.2018
comment
@Ilhan Я только что внес изменение, которое должно исправить ошибку. - person cdiggins; 28.08.2018
comment
Поиск в этой реализации работает некорректно для случаев, когда есть 2 совпадения. - person Anton; 19.06.2020