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 } } ; }
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 } } ; }