< Summary

Information
Class: MoreStructures.SuffixStructures.Matching.NaiveSnssFinder
Assembly: MoreStructures
File(s): /home/runner/work/MoreStructures/MoreStructures/MoreStructures/SuffixStructures/Matching/NaiveSnssFinder.cs
Line coverage
100%
Covered lines: 15
Uncovered lines: 0
Coverable lines: 15
Total lines: 64
Line coverage: 100%
Branch coverage
100%
Covered branches: 2
Total branches: 2
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
Find(...)100%2100%

File(s)

/home/runner/work/MoreStructures/MoreStructures/MoreStructures/SuffixStructures/Matching/NaiveSnssFinder.cs

#LineLine coverage
 1using MoreStructures.Utilities;
 2
 3namespace MoreStructures.SuffixStructures.Matching;
 4
 5/// <summary>
 6/// A <see cref="ISnssFinder"/> implementation which checks for the presence of each substring of the first text in the
 7/// second text, from the longest to the shortest.
 8/// </summary>
 9/// <remarks>
 10///     <para id="advantages">
 11///     ADVANTAGES AND DISADVANTAGES
 12///     <br/>
 13///     - Unlike <see cref="SuffixStructureBasedSnssFinder"/> derivations, this implementation doesn't require
 14///       terminators, since it does not build any auxialiary structure.
 15///       <br/>
 16///     - It also doesn't require additional space, except for iterations and index variables. So, it's a good
 17///       solution for small input, when space is a hard constraint, much more than time.
 18///     </para>
 19///     <para id="algo">
 20///     ALGORITHM
 21///     <br/>
 22///     - Lazily iterates over all substrings of text1, from the shortest (length 1) to the longest (length - 1).
 23///       <br/>
 24///     - As soon as it finds one which is not contained in text2, it yield returns it.
 25///     </para>
 26///     <para id="complexity">
 27///     COMPLEXITY
 28///     <br/>
 29///     - Checking all substrings of text1 of variable length, from 1 to length - 1, is a quadratic with the length of
 30///       text1. It doesn't require more than constant space (for iterators and index variables) when using string
 31///       ranges (which are views of larger strings, optimized thanks to immutability.
 32///       <br/>
 33///     - Each check of a substring of text1 in text2 takes O(sl) time, where sl is the length of the substring. Since
 34///       the average length of the substring depends linearly on the length of text1 n, the check takes O(n).
 35///       <br/>
 36///     - So overall Time Complexity is O(n^3) and Space Complexity is O(1).
 37///     </para>
 38/// </remarks>
 39public class NaiveSnssFinder : ISnssFinder
 40{
 41    /// <inheritdoc path="//*[not(self::remarks)]"/>
 42    /// <remarks>
 43    ///     <inheritdoc cref="NaiveSnssFinder" path="/remarks"/>
 44    /// </remarks>
 45    public IEnumerable<string> Find(IEnumerable<char> text1, IEnumerable<char> text2)
 1446    {
 1447        var string1 = string.Concat(text1);
 1448        var string2 = string.Concat(text2);
 49
 1450        if (string2.Contains(string1))
 351            return Enumerable.Empty<string>();
 52
 1153        var results =
 1154            from length in Enumerable.Range(1, string1.Length) // All substrings of non-zero length
 31755            from start in Enumerable.Range(0, string1.Length - length + 1)
 23156            let substringOfString1 = string1[start..(start + length)]
 23157            where !string2.Contains(substringOfString1)
 6658            select substringOfString1;
 59
 1160        var (firstOrEmpty, _) = results.EnumerateAtMostFirst(1);
 1161        var first = firstOrEmpty.Single();
 5562        return results.TakeWhile(s => s.Length == first.Length).Prepend(first);
 1463    }
 64}