From ac605de16c0cc0b57993411cb2f0c7caead194cb Mon Sep 17 00:00:00 2001 From: SashaRey Date: Tue, 24 Dec 2024 23:48:42 +0500 Subject: [PATCH] Update boyer-moore.js --- BoyerMoore/boyer-moore.js | 95 ++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 42 deletions(-) diff --git a/BoyerMoore/boyer-moore.js b/BoyerMoore/boyer-moore.js index b473825..54b591f 100644 --- a/BoyerMoore/boyer-moore.js +++ b/BoyerMoore/boyer-moore.js @@ -1,71 +1,82 @@ function boyerMooreSearch(text, pattern) { const textLength = text.length; const patternLength = pattern.length; + const result = []; // Функция для создания таблицы плохих символов function buildBadCharTable(pattern) { const table = {}; for (let i = 0; i < pattern.length; i++) { - table[pattern[i]] = i; + table[pattern[i]] = i + 1; } return table; } - // Функция для вычисления сдвига по хорошему суффиксу - function goodSuffix(pattern, l) { - function rpr(l, pattern) { - const m = pattern.length; - const extendedPattern = '*'.repeat(m) + pattern; - - for (let k = m - l; k >= -m + 1; k--) { - const segment = extendedPattern.slice(k + m, k + m + l); - const suffix = pattern.slice(m - l); + // Препроцессинг правила хорошего суффикса, когда мы его находим в шаблоне +function preprocessStrongSuffix(shift, suffixPos, pattern, m) { + let i = m; //начнем с конца шаблона + let j = m + 1; //указывает на начало суффикса + suffixPos[i] = j; //массив, который будет хранить информацию о позициях + - if ( - segment === suffix && - (k <= 0 || pattern[k - 1] !== pattern[m - l - 1]) - ) { - return k; - } + while (i > 0) { // Идем по шаблону с конца. + // Если суффикс в шаблоне совпадает с его частью, продолжаем двигаться. + while (j <= m && pattern[i - 1] !== pattern[j - 1]) { + if (shift[j] === 0) { // Если сдвиг еще не был рассчитан для позиции j. + shift[j] = j - i; // Записываем сдвиг } + j = suffixPos[j]; // Переход к следующему суффиксу + } + i--; // Переходим к следующей позиции в шаблоне. + j--; // Переходим к следующему суффиксу. + suffixPos[i] = j; // Сохраняем позицию текущего суффикса. + } - return -m + 1; + // Вывод таблицы сдвигов для хорошего суффикса + console.table(shift); // Выводим таблицу сдвигов +} + +// Препроцессинг для случая 2, когда для текущего суффикса не было найдено совпадений +function preprocessCase2(shift, suffixPos, m) { + let j = suffixPos[0]; // Начинаем с самого длинного суффикса. + for (let i = 0; i <= m; i++) { + if (shift[i] === 0) { + shift[i] = j; // Заполняем таблицу сдвигов для слабых суффиксов. } - const m = pattern.length; - const k = rpr(l, pattern); - return m - k - l + 1; + if (i === j) { + j = suffixPos[j]; // Если достигли конца суффикса, переходим к следующему + } } +} - const badCharTable = buildBadCharTable(pattern); - const result = []; + const badCharTable = buildBadCharTable(pattern); // Таблица плохих символов + + const shift = new Array(patternLength + 1).fill(0); + const suffixPos = new Array(patternLength + 1); + preprocessStrongSuffix(shift, suffixPos, pattern, patternLength); + preprocessCase2(shift, suffixPos, patternLength); + + console.log("Таблица плохих символов:", badCharTable); + console.table(shift.map((value, index) => ({ Index: index, Shift: value }))); - let shift = 0; // Смещение шаблона относительно текста - while (shift <= (textLength - patternLength)) { + let s = 0; // Смещение шаблона относительно текста + while (s <= textLength - patternLength) { let j = patternLength - 1; // Сравниваем символы справа налево - while (j >= 0 && pattern[j] === text[shift + j]) { + while (j >= 0 && pattern[j] === text[s + j]) { j--; } if (j < 0) { // Найдено совпадение - result.push(shift); - // Смещение шаблона на следующую возможную позицию - shift += patternLength; + result.push(s); + s += shift[0]; } else { - // Вычисляем длину совпавшего суффикса - let l = 0; - while (l < patternLength && text[shift + patternLength - 1 - l] === pattern[patternLength - 1 - l]) { - l++; - } - - // Используем таблицу плохих символов для смещения - const badCharShift = j - (badCharTable[text[shift + j]] || -1); - const goodSuffixShift = l > 0 ? goodSuffix(pattern, l) : 1; - - // Итоговый сдвиг - shift += Math.max(goodSuffixShift, badCharShift); + // Используем таблицу плохих символов и правила хорошего суффикса + const badCharShift = (badCharTable[text[s + j]] ?? 0); + const goodSuffixShift = shift[j + 1]; + s += Math.max(patternLength - badCharShift - 1, goodSuffixShift); } } @@ -73,7 +84,7 @@ function boyerMooreSearch(text, pattern) { } // Пример использования -const text = "abccabcbbccabcdabcdabc"; -const pattern = "abc"; +const text = "abcabcabbccabcdabcdabc"; +const pattern = "abcdabc"; const result = boyerMooreSearch(text, pattern); console.log("Позиции совпадений:", result);