-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e6a20a5
commit 8057d4d
Showing
8 changed files
with
10,197 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,8 @@ | ||
# Usage | ||
|
||
> :warning: Depending on your environment, the code may require | ||
> `regeneratorRuntime` to be defined, for instance by importing | ||
> [regenerator-runtime/runtime](https://www.npmjs.com/package/regenerator-runtime). | ||
First, require the polyfill at the entry point of your application | ||
```js | ||
require( 'regenerator-runtime/runtime' ) ; | ||
// or | ||
import 'regenerator-runtime/runtime.js' ; | ||
``` | ||
|
||
Then, import the library where needed | ||
Import the library where needed | ||
```js | ||
const failureFunction = require( '@string-data-structure/failure-function' ) ; | ||
const {build} = require( '@string-data-structure/failure-function' ) ; | ||
// or | ||
import * as failureFunction from '@string-data-structure/failure-function' ; | ||
import {build} from '@string-data-structure/failure-function' ; | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/** | ||
* Computes the failure function for input string. | ||
* | ||
* This is the "next[j]" table found in | ||
* "Fast pattern matching in strings" by Knuth, Morris, and Pratt, | ||
* although here indices are 0-based hence all indices and inputs are one less | ||
* than in that paper. | ||
* | ||
* NOTE The main loop is somewhat unrolled for faster execution. This was not | ||
* benchmarked. | ||
* | ||
* @param {ArrayLike} p | ||
* @param {number} pi | ||
* @param {number} pj | ||
* @param {number[]} t | ||
* @param {number} ti | ||
*/ | ||
const build = (p, pi, pj, t, ti) => { | ||
t[ti] = -1; | ||
if (pi === pj) return; | ||
const p0 = pi; | ||
if (++pi === pj) { | ||
t[++ti] = 0; | ||
return; | ||
} | ||
|
||
const t0 = ti; | ||
t[++ti] = p[pi] === p[p0] ? -1 : 0; | ||
let m = 0; | ||
--pj; | ||
while (pi < pj) { | ||
while (p[pi] !== p[p0 + m]) { | ||
m = t[t0 + m]; | ||
if (m === -1) break; | ||
} | ||
|
||
++m; | ||
t[++ti] = p[++pi] === p[p0 + m] ? t[t0 + m] : m; | ||
} | ||
|
||
while (p[pj] !== p[p0 + m]) { | ||
m = t[t0 + m]; | ||
if (m === -1) break; | ||
} | ||
|
||
++m; | ||
t[++ti] = m; | ||
}; | ||
|
||
export default build; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1 @@ | ||
const answer = 42; | ||
export default answer; | ||
export {default as build} from './build.js'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import {build} from '../../src/index.js'; | ||
|
||
const _table = (p, pi, pj) => { | ||
// eslint-disable-next-line unicorn/no-new-array | ||
const next = new Array(pj - pi + 1); | ||
build(p, pi, pj, next, 0); | ||
return next; | ||
}; | ||
|
||
export const table = (input) => _table(input, 0, input.length); |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import test from 'ava'; | ||
|
||
import {table} from './_fixtures.js'; | ||
|
||
const isNext = (t, table, input) => { | ||
if (input === '') { | ||
t.deepEqual(table, [-1]); | ||
return; | ||
} | ||
|
||
// TODO this test is not complete | ||
|
||
t.is(table[0], -1); | ||
t.not(table[input.length], -1); | ||
for (let j = 1; j <= input.length; ++j) { | ||
const i = table[j]; | ||
// TODO test when i === -1 | ||
if (i !== -1) { | ||
// Prefix and suffix match | ||
t.true(input.slice(0, i) === input.slice(j - i, j)); | ||
// Next character does not match | ||
t.true(j === input.length || input[i] !== input[j]); | ||
// A longer proper prefix/suffix pair does not match | ||
// TODO More possibilities need to be checked | ||
t.true( | ||
i + 1 === j || | ||
input.slice(0, i + 1) !== input.slice(j - (i + 1), j) || | ||
i + 2 === j || | ||
j === input.length || | ||
input[i + 1] === input[j], | ||
); | ||
} | ||
} | ||
}; | ||
|
||
const macro = (t, input, expected) => { | ||
const next = table(input); | ||
t.deepEqual(next, expected); | ||
isNext(t, next, input); | ||
}; | ||
|
||
macro.title = (title, input, expected) => | ||
title ?? `next(${input}) is ${JSON.stringify(expected)}`; | ||
|
||
const auto = (t, input) => { | ||
const next = table(input); | ||
isNext(t, next, input); | ||
}; | ||
|
||
auto.title = (title, input) => title ?? `isNext(next(${input}))`; | ||
|
||
test(macro, '', [-1]); | ||
test(macro, 'z', [-1, 0]); | ||
test(macro, 'abcd', [-1, 0, 0, 0, 0]); | ||
test(macro, 'aaaa', [-1, -1, -1, -1, 3]); | ||
test(macro, 'axax', [-1, 0, -1, 0, 2]); | ||
test(macro, 'axxa', [-1, 0, 0, -1, 1]); | ||
test(macro, 'aaaab', [-1, -1, -1, -1, 3, 0]); | ||
test(macro, 'abracadabra', [-1, 0, 0, -1, 1, -1, 1, -1, 0, 0, -1, 4]); | ||
test( | ||
macro, | ||
'abaababaabaababaababa', | ||
[-1, 0, -1, 1, 0, -1, 3, -1, 1, 0, -1, 6, 0, -1, 3, -1, 1, 0, -1, 11, -1, 8], | ||
); | ||
|
||
test(auto, 'eifoiwhfeldkasjflkdshfldshflkkdadkkkkkkkkkkkkasjfdljfdleifo'); | ||
test(auto, 'aaaaaaaaaaaabbbbbbbbbbaaaaaaaaabbbbbbbb'); |
Oops, something went wrong.