Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 53 additions & 42 deletions BoyerMoore/boyer-moore.js
Original file line number Diff line number Diff line change
@@ -1,79 +1,90 @@
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);
}
}

return result;
}

// Пример использования
const text = "abccabcbbccabcdabcdabc";
const pattern = "abc";
const text = "abcabcabbccabcdabcdabc";
const pattern = "abcdabc";
const result = boyerMooreSearch(text, pattern);
console.log("Позиции совпадений:", result);