diff --git a/DIRECTORY.md b/DIRECTORY.md index c9b08760a..db5f61980 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -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 000000000..6ec8108b7 --- /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 }