|
| 1 | +/* |
| 2 | + * |
| 3 | + * |
| 4 | + *Implementation of the Boyer-Moore String Search Algorithm. |
| 5 | + *The Boyer–Moore string search algorithm allows linear time in |
| 6 | + *search by skipping indices when searching inside a string for a pattern. |
| 7 | + * |
| 8 | + * |
| 9 | + * |
| 10 | + * |
| 11 | + **/ |
| 12 | +const buildBadMatchTable = (str) => { |
| 13 | + const tableObj = {} |
| 14 | + const strLength = str.length |
| 15 | + for (let i = 0; i < strLength - 1; i++) { |
| 16 | + tableObj[str[i]] = strLength - 1 - i |
| 17 | + } |
| 18 | + if (tableObj[str[strLength - 1]] === undefined) { |
| 19 | + tableObj[str[strLength - 1]] = strLength |
| 20 | + } |
| 21 | + return tableObj |
| 22 | +} |
| 23 | + |
| 24 | +const boyerMoore = (str, pattern) => { |
| 25 | + const badMatchTable = buildBadMatchTable(pattern) |
| 26 | + let offset = 0 |
| 27 | + const patternLastIndex = pattern.length - 1 |
| 28 | + const maxOffset = str.length - pattern.length |
| 29 | + // if the offset is bigger than maxOffset, cannot be found |
| 30 | + while (offset <= maxOffset) { |
| 31 | + let scanIndex = 0 |
| 32 | + while (pattern[scanIndex] === str[scanIndex + offset]) { |
| 33 | + if (scanIndex === patternLastIndex) { |
| 34 | + // found at this index |
| 35 | + return offset |
| 36 | + } |
| 37 | + scanIndex++ |
| 38 | + } |
| 39 | + const badMatchString = str[offset + patternLastIndex] |
| 40 | + if (badMatchTable[badMatchString]) { |
| 41 | + // increase the offset if it exists |
| 42 | + offset += badMatchTable[badMatchString] |
| 43 | + } else { |
| 44 | + offset++ |
| 45 | + } |
| 46 | + } |
| 47 | + return -1 |
| 48 | +} |
| 49 | +export { boyerMoore } |
0 commit comments