예제 #1
0
        private static void VerifyAllSuffixes(string[] strings, IEnumerable <Suffix> result)
        {
            var expectedSuffixes = new List <string>();
            var expectedSources  = new LazyDictionary <string, List <int> >(_ => new List <int>());

            for (var i = 0; i < strings.Length; ++i)
            {
                var s = strings[i];
                for (var j = 0; j < s.Length; ++j)
                {
                    var suffix = s.Substring(j);
                    expectedSuffixes.Add(suffix);
                    expectedSources[suffix].Add(i);
                }
            }
            expectedSuffixes.Sort();
            var suffixes = result.ToList();

            Assert.That(suffixes.Select(_ => _.Value).ToList(), Is.EqualTo(expectedSuffixes));
            var grouped = suffixes.Select(_ => new { value = _.Value, source = _.SourceIndex })
                          .GroupBy(_ => _.value).ToDictionary(_ => _.Key, _ => _.Select(v => v.source).OrderBy(v => v).ToList());

            foreach (var v in grouped)
            {
                Assert.That(v.Value, Is.EqualTo(expectedSources[v.Key]));
            }
        }
예제 #2
0
        private static void TestStartingWith(string[] strings)
        {
            var prefixes = new HashSet <string>();
            var st       = new SuffixTree();

            foreach (var s in strings)
            {
                st.Add(s);
                for (var i = 0; i < s.Length; ++i)
                {
                    for (var j = i + 1; j <= s.Length; ++j)
                    {
                        prefixes.Add(s.Substring(i, j - i));
                    }
                }
            }
            st.Compact();
            foreach (var prefix in prefixes)
            {
                var expectedSuffixes = new List <string>();
                var expectedSources  = new LazyDictionary <string, List <int> >(_ => new List <int>());
                for (var i = 0; i < strings.Length; ++i)
                {
                    var s   = strings[i];
                    var pos = 0;
                    for (;;)
                    {
                        pos = s.IndexOf(prefix, pos);
                        if (pos == -1)
                        {
                            break;
                        }
                        var suffix = s.Substring(pos);
                        expectedSuffixes.Add(suffix);
                        expectedSources[suffix].Add(i);
                        ++pos;
                    }
                }
                expectedSuffixes.Sort();
                var suffixes = st.StartingWith(prefix).ToList();
                Assert.That(suffixes.Select(_ => _.Value).ToList(), Is.EqualTo(expectedSuffixes));
                var grouped = suffixes.Select(_ => new { value = _.Value, source = _.SourceIndex })
                              .GroupBy(_ => _.value).ToDictionary(_ => _.Key, _ => _.Select(v => v.source).OrderBy(v => v).ToList());
                foreach (var v in grouped)
                {
                    Assert.That(v.Value, Is.EqualTo(expectedSources[v.Key]));
                }
            }
            Assert.That(st.StartingWith("@").Count(), Is.EqualTo(0));
            VerifyAllSuffixes(strings, st.StartingWith(string.Empty));
        }
        public static IEnumerable <T[]> GroupTopoSort <T>(
            this ICollection <T> source,
            [InstantHandle] Func <T, IEnumerable <T> > dependsOnGetter,
            IEqualityComparer <T> equalityComparer)
            where T : notnull
        {
            Code.NotNull(source, nameof(source));
            Code.NotNull(dependsOnGetter, nameof(dependsOnGetter));
            Code.NotNull(equalityComparer, nameof(equalityComparer));

            // Fast path
            if (source.Count == 0)
            {
                yield break;
            }

            var dependants =
                LazyDictionary.Create(
                    _ => new List <T>(),
                    equalityComparer,
                    false);
            var workArray = new int[source.Count];
            var indices   = new Dictionary <T, int>(equalityComparer);
            var level     = new List <T>();

            foreach (var(index, item) in source.WithIndex())
            {
                var count = 0;
                foreach (var dep in dependsOnGetter(item))
                {
                    dependants[dep].Add(item);
                    count++;
                }
                if (count == 0)
                {
                    level.Add(item);
                }
                else
                {
                    workArray[index] = count;
                }
                indices.Add(item, index);
            }

            if (level.Count == 0)
            {
                throw CycleException(nameof(source));
            }

            // Fast path
            if (level.Count == workArray.Length)
            {
                yield return(level.ToArray());

                yield break;
            }

            var pendingCount = workArray.Length;

            while (true)
            {
                var nextLevel = Lazy.Create(() => new List <T>(), false);
                foreach (var item in level)
                {
                    foreach (var dep in dependants[item])
                    {
                        var pending = --workArray[indices[dep]];
                        if (pending == 0)
                        {
                            nextLevel.Value.Add(dep);
                        }
                    }
                }
                yield return(level.ToArray());

                pendingCount -= level.Count;
                if (pendingCount == 0)
                {
                    yield break;
                }
                if (!nextLevel.IsValueCreated)
                {
                    throw CycleException(nameof(source));
                }
                level = nextLevel.Value;
            }
        }