//Эвристика хорошего суффикса
        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];
                }
            }
        }