Skip to content

Commit a513631

Browse files
authored
Create AhoCorasick.js
1 parent de65f40 commit a513631

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

src/AhoCorasick.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
var AhoCorasick = function (keywords) {
2+
this._buildTables(keywords)
3+
}
4+
5+
AhoCorasick.prototype._buildTables = function (keywords) {
6+
var gotoFn = {
7+
0: {},
8+
}
9+
var output = {}
10+
11+
var state = 0
12+
keywords.forEach(function (word) {
13+
var curr = 0
14+
for (var i = 0; i < word.length; i++) {
15+
var l = word[i]
16+
if (gotoFn[curr] && l in gotoFn[curr]) {
17+
curr = gotoFn[curr][l]
18+
} else {
19+
state++
20+
gotoFn[curr][l] = state
21+
gotoFn[state] = {}
22+
curr = state
23+
output[state] = []
24+
}
25+
}
26+
27+
output[state].push(word)
28+
})
29+
30+
var failure = {}
31+
var xs = []
32+
33+
// f(s) = 0 for all states of depth 1 (the ones just from which 0 can directly transition)
34+
for (var l in gotoFn[0]) {
35+
var state = gotoFn[0][l]
36+
failure[state] = 0
37+
xs.push(state)
38+
}
39+
40+
while (xs.length) {
41+
var r = xs.shift()
42+
// for each symbol a such that g(r, a) = s
43+
for (var l in gotoFn[r]) {
44+
var s = gotoFn[r][l]
45+
xs.push(s)
46+
47+
// set state = f(r)
48+
var state = failure[r]
49+
while (state > 0 && !(l in gotoFn[state])) {
50+
state = failure[state]
51+
}
52+
53+
if (l in gotoFn[state]) {
54+
var fs = gotoFn[state][l]
55+
failure[s] = fs
56+
output[s] = output[s].concat(output[fs])
57+
} else {
58+
failure[s] = 0
59+
}
60+
}
61+
}
62+
63+
this.gotoFn = gotoFn
64+
this.output = output
65+
this.failure = failure
66+
}
67+
68+
AhoCorasick.prototype.search = function (string) {
69+
var state = 0
70+
var results = []
71+
for (var i = 0; i < string.length; i++) {
72+
var l = string[i]
73+
while (state > 0 && !(l in this.gotoFn[state])) {
74+
state = this.failure[state]
75+
}
76+
if (!(l in this.gotoFn[state])) {
77+
continue
78+
}
79+
80+
state = this.gotoFn[state][l]
81+
82+
if (this.output[state].length) {
83+
var foundStrs = this.output[state]
84+
results.push([i, foundStrs])
85+
}
86+
}
87+
88+
return results
89+
}

0 commit comments

Comments
 (0)