diff --git a/DIRECTORY.md b/DIRECTORY.md index 8613c684c8..db5f619802 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -77,7 +77,7 @@ * [CycleDetection](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Linked-List/CycleDetection.js) * [DoublyLinkedList](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Linked-List/DoublyLinkedList.js) * [RotateListRight](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Linked-List/RotateListRight.js) - * [SingleCircularLinkedList](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Linked-List/SingleCircularLinkedList.js.js) + * [SinglyCircularLinkedList](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Linked-List/SinglyCircularLinkedList.js) * [SinglyLinkedList](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Linked-List/SinglyLinkedList.js) * Queue * [CircularQueue](https://github.com/TheAlgorithms/Javascript/blob/master/Data-Structures/Queue/CircularQueue.js) @@ -295,6 +295,7 @@ ## String * [AlphaNumericPalindrome](https://github.com/TheAlgorithms/Javascript/blob/master/String/AlphaNumericPalindrome.js) * [AlternativeStringArrange](https://github.com/TheAlgorithms/Javascript/blob/master/String/AlternativeStringArrange.js) + * [BoyerMoore](https://github.com/TheAlgorithms/Javascript/blob/master/String/BoyerMoore.js) * [CheckAnagram](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckAnagram.js) * [CheckCamelCase](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckCamelCase.js) * [CheckExceeding](https://github.com/TheAlgorithms/Javascript/blob/master/String/CheckExceeding.js) diff --git a/String/BoyerMoore.js b/String/BoyerMoore.js new file mode 100644 index 0000000000..6ec8108b71 --- /dev/null +++ b/String/BoyerMoore.js @@ -0,0 +1,49 @@ +/* + * + * + *Implementation of the Boyer-Moore String Search Algorithm. + *The Boyer–Moore string search algorithm allows linear time in + *search by skipping indices when searching inside a string for a pattern. + * + * + * + * + **/ +const buildBadMatchTable = (str) => { + const tableObj = {} + const strLength = str.length + for (let i = 0; i < strLength - 1; i++) { + tableObj[str[i]] = strLength - 1 - i + } + if (tableObj[str[strLength - 1]] === undefined) { + tableObj[str[strLength - 1]] = strLength + } + return tableObj +} + +const boyerMoore = (str, pattern) => { + const badMatchTable = buildBadMatchTable(pattern) + let offset = 0 + const patternLastIndex = pattern.length - 1 + const maxOffset = str.length - pattern.length + // if the offset is bigger than maxOffset, cannot be found + while (offset <= maxOffset) { + let scanIndex = 0 + while (pattern[scanIndex] === str[scanIndex + offset]) { + if (scanIndex === patternLastIndex) { + // found at this index + return offset + } + scanIndex++ + } + const badMatchString = str[offset + patternLastIndex] + if (badMatchTable[badMatchString]) { + // increase the offset if it exists + offset += badMatchTable[badMatchString] + } else { + offset++ + } + } + return -1 +} +export { boyerMoore }