//Эвристика хорошего суффикса private int[] ComputeGoodSuffixFunction(string str) { var pi = PrefixFunction.Compute(str); var piRev = PrefixFunction.Compute(ReverseString(str)); var gamma = new int[(long)str.Length + 1]; // В массивах pi и piRev относительно Кормена индексы начинаются с нуля // при этом в gamma нумерация идет как и в книге for (int j = 0, initialShift = str.Length - pi[str.Length - 1]; j < gamma.Length; j++) { gamma[j] = initialShift; } for (int l = 1; l < gamma.Length; l++) { var j = str.Length - piRev[l - 1]; var shift = l - piRev[l - 1]; if (gamma[j] > shift) { gamma[j] = shift; } } return(gamma); }
/// <summary> /// Находит все вхождения образца в строку, в которой осуществляется поиск. /// </summary> /// <returns> /// Перечисление индексов вхождения образца в строку, в которой осуществляется поиск, /// в порядке возрастания. /// </returns> /// <exception cref="System.ArgumentNullException">text или pattern null</exception> /// <param name = "pattern">Строка, вхождения которой нужно найти.</param> /// <param name = "text">Строка, в которой осуществляется поиск.</param> public IEnumerable <int> GetAllEntries(string pattern, string text) { if (text == null) { throw new ArgumentNullException("text is null."); } if (pattern == null) { throw new ArgumentNullException("pattern is null."); } if (pattern == string.Empty) { for (int i = 0; i <= text.Length; i++) { yield return(i); } yield break; } var pi = PrefixFunction.Compute(pattern); for (int i = 0, j = 0; i < text.Length; i++) { while ((j > 0) && (pattern[j] != text[i])) { j = pi[j - 1]; } if (pattern[j] == text[i]) { j++; } if (j == pattern.Length) { yield return(i - j + 1); j = pi[j - 1]; } } }