Example #1
0
    public static IEnumerable <NeedleResult3> ConsiderThreePlusCleaned(IEnumerable <string> needles0, string haystack, CancellationToken cancel)
    {
        IList <string> needles = (needles0 as IList <string>) ?? new List <string>(needles0);

        if (needles == null)
        {
            throw new ArgumentNullException(nameof(needles));
        }
        if (haystack == null)
        {
            throw new ArgumentNullException(nameof(haystack));
        }
        if (needles.Any(string.IsNullOrEmpty))
        {
            throw new ArgumentNullException(nameof(needles));
        }

        Tuple <int, char>             oneMatch   = Tuple.Create(-1, '\0');
        Tuple <int, char, char>       twoMatch   = Tuple.Create(-1, '\0', '\0');
        Tuple <int, char, char, char> threeMatch = Tuple.Create(-1, '\0', '\0', '\0');
        var threePlusMatches = new Dictionary <long, List <int> >();

        for (int ni = 0; ni < needles.Count; ni++)
        {
            var needle = needles[ni];
            if (needle.Length == 1)
            {
                oneMatch = Tuple.Create(ni, needle[0]);
            }
            else if (needle.Length == 2)
            {
                twoMatch = Tuple.Create(ni, needle[0], needle[1]);
            }
            else if (needle.Length == 3)
            {
                threeMatch = Tuple.Create(ni, needle[0], needle[1], needle[2]);
            }
            else
            {
                long three = needle[0] | (needle[1] << 16) | (needle[2] << 24);
                if (!threePlusMatches.ContainsKey(three))
                {
                    threePlusMatches[three] = new List <int>();
                }
                threePlusMatches[three].Add(ni);
            }
        }

        var underConsiderations = new LinkedList <NeedleResult3>();
        var xcount = 0;
        int reportNeedle = -1, reportLength = -1;

        for (int ic = 0; ic < haystack.Length - 2; ic++)
        {
            if (ic % 100 == 0 && cancel.IsCancellationRequested)
            {
                yield break;
            }

            var c = haystack[ic];
            xcount++;

            // Consider all the ones we've had so far
            for (LinkedListNode <NeedleResult3> uc = underConsiderations.First; uc != null;)
            {
                var needle = needles[uc.Value.Needle];
                if (needle[uc.Value.Length] == c)
                {
                    uc.Value = new NeedleResult3 {
                        Needle = uc.Value.Needle, Length = uc.Value.Length + 1
                    };
                    if (uc.Value.Length == needle.Length)
                    {
                        if (xcount > needle.Length)
                        {
                            yield return new NeedleResult3 {
                                       Needle = -1, Start = ic + 1 - xcount, Length = xcount - needle.Length
                            }
                        }
                        ;
                        yield return(new NeedleResult3 {
                            Needle = uc.Value.Needle, Start = ic + 1 - needle.Length, Length = needle.Length
                        });

                        xcount = 0;
                        underConsiderations.Clear();
                        goto nextchar;
                    }
                    uc = uc.Next;
                }
                else
                {
                    var temp = uc.Next;
                    underConsiderations.Remove(uc);
                    uc = temp;
                }
            }

            if (oneMatch.Item2 == c)
            {
                reportNeedle = oneMatch.Item1; reportLength = 1;
            }
            else if (twoMatch.Item2 == c && twoMatch.Item3 == haystack[ic + 1])
            {
                reportNeedle = twoMatch.Item1; reportLength = 2;
            }
            else if (threeMatch.Item2 == c && threeMatch.Item3 == haystack[ic + 1] && threeMatch.Item4 == haystack[ic + 2])
            {
                reportNeedle = threeMatch.Item1; reportLength = 3;
            }
            else
            {
                long       three = c | (haystack[ic + 1] << 16) | (haystack[ic + 2] << 24);
                List <int> l; if (threePlusMatches.TryGetValue(three, out l))
                {
                    foreach (var i in l)
                    {
                        var uc = new NeedleResult3 {
                            Needle = i, Length = 1
                        };
                        underConsiderations.AddLast(uc);
                    }
                }
                continue;
            }
            if (xcount > 1)
            {
                yield return new NeedleResult3 {
                           Needle = -1, Start = ic + 1 - xcount, Length = xcount - 1
                }
            }
            ;
            yield return(new NeedleResult3 {
                Needle = reportNeedle, Start = ic, Length = reportLength
            });

            ic    += reportLength - 1;
            xcount = 0;
            underConsiderations.Clear();

            nextchar :;
        }

        if (xcount > 0)
        {
            yield return new NeedleResult3 {
                       Needle = -1, Start = haystack.Length - xcount, Length = xcount
            }
        }
        ;
    }
Example #2
0
    public static IEnumerable <NeedleResult3> ConsiderSomeSimultaneously(IEnumerable <string> needles0, string haystack, CancellationToken cancel)
    {
        IList <string> needles = (needles0 as IList <string>) ?? new List <string>(needles0);

        if (needles == null)
        {
            throw new ArgumentNullException(nameof(needles));
        }
        if (haystack == null)
        {
            throw new ArgumentNullException(nameof(haystack));
        }
        if (needles.Any(string.IsNullOrEmpty))
        {
            throw new ArgumentNullException(nameof(needles));
        }

        Tuple <char, int> oneMatch = null;
        var onePlusMatches         = new Dictionary <char, List <int> >();

        for (int ni = 0; ni < needles.Count; ni++)
        {
            var needle = needles[ni];
            var c      = needle[0];
            if (needle.Length == 1)
            {
                oneMatch = Tuple.Create(c, ni);
            }
            else
            {
                List <int> l; if (!onePlusMatches.TryGetValue(c, out l))
                {
                    l = new List <int>(); onePlusMatches.Add(c, l);
                }
                l.Add(ni);
            }
        }

        var underConsiderations = new LinkedList <NeedleResult3>();

        var xcount = 0;

        for (int ic = 0; ic < haystack.Length; ic++)
        {
            if (ic % 100 == 0 && cancel.IsCancellationRequested)
            {
                yield break;
            }

            var c = haystack[ic];
            xcount++;

            // Consider all the ones we've had so far
            for (LinkedListNode <NeedleResult3> uc = underConsiderations.First; uc != null;)
            {
                var needle = needles[uc.Value.Needle];
                if (needle[uc.Value.Length] == c)
                {
                    uc.Value = new NeedleResult3 {
                        Needle = uc.Value.Needle, Length = uc.Value.Length + 1
                    };
                    if (uc.Value.Length == needle.Length)
                    {
                        if (xcount > needle.Length)
                        {
                            yield return new NeedleResult3 {
                                       Needle = -1, Start = ic + 1 - xcount, Length = xcount - needle.Length
                            }
                        }
                        ;
                        yield return(new NeedleResult3 {
                            Needle = uc.Value.Needle, Start = ic + 1 - needle.Length, Length = needle.Length
                        });

                        xcount = 0;
                        underConsiderations.Clear();
                        goto nextchar;
                    }
                    uc = uc.Next;
                }
                else
                {
                    var tuc = uc.Next;
                    underConsiderations.Remove(uc);
                    uc = tuc;
                }
            }

            // Consider the one-match
            if (oneMatch != null && oneMatch.Item1 == c)
            {
                if (xcount > 1)
                {
                    yield return new NeedleResult3 {
                               Needle = -1, Start = ic + 1 - xcount, Length = xcount - 1
                    }
                }
                ;
                yield return(new NeedleResult3 {
                    Needle = oneMatch.Item2, Start = ic, Length = 1
                });

                xcount = 0;
                underConsiderations.Clear();
                goto nextchar;
            }

            // Consider the one+ matches
            List <int> l; if (onePlusMatches.TryGetValue(c, out l))
            {
                foreach (var i in l)
                {
                    var uc = new NeedleResult3 {
                        Needle = i, Length = 1
                    };

                    underConsiderations.AddLast(uc);
                }
            }
            nextchar :;
        }

        if (xcount > 0)
        {
            yield return new NeedleResult3 {
                       Needle = -1, Start = haystack.Length - xcount, Length = xcount
            }
        }
        ;
    }