< Summary

Information
Class: MoreStructures.SuffixStructures.Matching.Matcher
Assembly: MoreStructures
File(s): /home/runner/work/MoreStructures/MoreStructures/MoreStructures/SuffixStructures/Matching/Matcher.cs
Line coverage
100%
Covered lines: 24
Uncovered lines: 0
Coverable lines: 24
Total lines: 77
Line coverage: 100%
Branch coverage
100%
Covered branches: 10
Total branches: 10
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
Match(...)100%1100%
Match(...)100%10100%

File(s)

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

#LineLine coverage
 1using MoreStructures.RecImmTrees;
 2using MoreStructures.Strings.Matching;
 3using static MoreStructures.Utilities.StringUtilities;
 4
 5namespace MoreStructures.SuffixStructures.Matching;
 6
 7/// <summary>
 8/// Exposes utility methods to match a <see cref="TextWithTerminator"/> against a
 9/// <see cref="ISuffixStructureNode{TEdge, TNode}"/> concretion.
 10/// </summary>
 11public static class Matcher
 12{
 13    /// <summary>
 14    /// Tries to match a pattern against a <see cref="ISuffixStructureNode{TEdge, TNode}"/> built on a text.
 15    /// </summary>
 16    /// <param name="node">The root of the Suffix Tree, to match the suffix of text against.</param>
 17    /// <param name="text">The text whose Suffix Tree has to be matched against the pattern.</param>
 18    /// <param name="pattern">The pattern to match. Unlike text, is a string without terminator.</param>
 19    /// <typeparam name="TEdge">
 20    ///     <inheritdoc cref="IRecImmDictIndexedTreeNode{TEdge, TNode}" path="/typeparam[@name='TEdge']"/>
 21    /// </typeparam>
 22    /// <typeparam name="TNode">
 23    ///     <inheritdoc cref="IRecImmDictIndexedTreeNode{TEdge, TNode}" path="/typeparam[@name='TNode']"/>
 24    /// </typeparam>
 25    /// <returns>A successful or non-successful match.</returns>
 26    /// <remarks>
 27    ///     <para id="complexity">
 28    ///     COMPLEXITY
 29    ///     <br/>
 30    ///     Time Complexity = O(t * as) and Space Complexity = O(t * as) where t = length of the text to match and
 31    ///     as = size of the alphabet of the text. If the alphabet is of constant size, complexity is linear.
 32    ///     </para>
 33    /// </remarks>
 34    public static Match<TreePath<TEdge, TNode>> Match<TEdge, TNode>(
 35        this ISuffixStructureNode<TEdge, TNode> node,
 36        TextWithTerminator text,
 37        string pattern)
 38        where TEdge : ISuffixStructureEdge<TEdge, TNode>
 39        where TNode : ISuffixStructureNode<TEdge, TNode> =>
 2840        Match(node, text, pattern, 0);
 41
 42    private static Match<TreePath<TEdge, TNode>> Match<TEdge, TNode>(
 43        this ISuffixStructureNode<TEdge, TNode> node,
 44        TextWithTerminator text,
 45        string pattern,
 46        int textStart)
 47        where TEdge : ISuffixStructureEdge<TEdge, TNode>
 48        where TNode : ISuffixStructureNode<TEdge, TNode>
 5949    {
 5950        if (string.IsNullOrEmpty(pattern))
 151            throw new ArgumentException("Must be non-null and non-emtpy.", nameof(pattern));
 52
 5853        var longestMatch = (
 5854            from edge in node.Children.Keys
 20655            let length = LongestCommonPrefix(edge.Of(text), pattern[textStart..])
 20656            select new { Length = length, Edge = edge })
 26457            .MaxBy(r => r.Length);
 58
 5859        if (longestMatch == null)
 560            return new Match<TreePath<TEdge, TNode>>(
 561                false, textStart, 0, new());
 62
 5363        if (longestMatch.Length == pattern.Length - textStart)
 2264            return new Match<TreePath<TEdge, TNode>>(
 2265                true, textStart + longestMatch.Edge.Start, longestMatch.Length, new());
 66
 67        // The edge has been fully matched but pattern is longer => chars left to match
 3168        var childNode = node.Children[longestMatch.Edge];
 3169        var childMatch = Match(childNode, text, pattern, textStart + longestMatch.Length);
 3170        var pathToChild = new TreePath<TEdge, TNode>(longestMatch.Edge, childNode);
 3171        return new Match<TreePath<TEdge, TNode>>(
 3172            childMatch.Success,
 3173            textStart + longestMatch.Edge.Start,
 3174            longestMatch.Length + childMatch.MatchedChars,
 3175            pathToChild.Concat(childMatch.Path));
 5876    }
 77}