mirror of
https://github.com/SukkaW/Surge.git
synced 2025-12-12 01:00:34 +08:00
Perf: Aho-Corasick node uses extends
This commit is contained in:
parent
5c3b86bce0
commit
7b6b14b1dc
@ -1,20 +1,14 @@
|
|||||||
const WORDEND = Symbol('wordEnd');
|
class Node extends Map<string, Node> {
|
||||||
const FAIL = Symbol('fail');
|
constructor(
|
||||||
|
public wordEnd: boolean,
|
||||||
type Node = Map<string, Node> & {
|
public fail: Node | undefined
|
||||||
[WORDEND]: boolean,
|
) {
|
||||||
[FAIL]: Node | undefined
|
super();
|
||||||
};
|
}
|
||||||
|
|
||||||
function createNode(): Node {
|
|
||||||
const node = new Map<string, Node | undefined>() as Node;
|
|
||||||
node[WORDEND] = false;
|
|
||||||
node[FAIL] = undefined;
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createKeywordFilter(keys: string[] | Set<string>) {
|
function createKeywordFilter(keys: string[] | Set<string>) {
|
||||||
const root = createNode();
|
const root = new Node(false, undefined);
|
||||||
|
|
||||||
// Create a trie with extra fields and information
|
// Create a trie with extra fields and information
|
||||||
const put = (key: string) => {
|
const put = (key: string) => {
|
||||||
@ -28,7 +22,7 @@ function createKeywordFilter(keys: string[] | Set<string>) {
|
|||||||
if (node.has(char)) {
|
if (node.has(char)) {
|
||||||
node = node.get(char)!;
|
node = node.get(char)!;
|
||||||
} else {
|
} else {
|
||||||
const newNode = createNode();
|
const newNode = new Node(false, undefined);
|
||||||
node.set(char, newNode);
|
node.set(char, newNode);
|
||||||
node = newNode;
|
node = newNode;
|
||||||
}
|
}
|
||||||
@ -36,7 +30,7 @@ function createKeywordFilter(keys: string[] | Set<string>) {
|
|||||||
|
|
||||||
// If a new node is created, mark it as a word end when loop finish
|
// If a new node is created, mark it as a word end when loop finish
|
||||||
if (node !== root) {
|
if (node !== root) {
|
||||||
node[WORDEND] = true;
|
node.wordEnd = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -49,13 +43,13 @@ function createKeywordFilter(keys: string[] | Set<string>) {
|
|||||||
const beginNode = queue.pop()!;
|
const beginNode = queue.pop()!;
|
||||||
|
|
||||||
beginNode.forEach((node, char) => {
|
beginNode.forEach((node, char) => {
|
||||||
let failNode = beginNode[FAIL];
|
let failNode = beginNode.fail;
|
||||||
|
|
||||||
while (failNode && !failNode.has(char)) {
|
while (failNode && !failNode.has(char)) {
|
||||||
failNode = failNode[FAIL];
|
failNode = failNode.fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
node[FAIL] = failNode ? failNode.get(char) : root;
|
node.fail = failNode ? failNode.get(char) : root;
|
||||||
|
|
||||||
queue.push(node);
|
queue.push(node);
|
||||||
});
|
});
|
||||||
@ -70,12 +64,12 @@ function createKeywordFilter(keys: string[] | Set<string>) {
|
|||||||
const char = text[i];
|
const char = text[i];
|
||||||
|
|
||||||
while (node && !node.has(char)) {
|
while (node && !node.has(char)) {
|
||||||
node = node[FAIL];
|
node = node.fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = node ? node.get(char)! : root;
|
node = node ? node.get(char)! : root;
|
||||||
|
|
||||||
if (node[WORDEND]) {
|
if (node.wordEnd) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user