-
Notifications
You must be signed in to change notification settings - Fork 357
/
AhoCorasick.java
87 lines (70 loc) · 2.64 KB
/
AhoCorasick.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import java.util.*;
public class AhoCorasick {
// Trie Node Class
static class TrieNode {
Map<Character, TrieNode> children = new HashMap<>();
TrieNode failureLink = null;
List<String> output = new ArrayList<>();
}
private TrieNode root = new TrieNode();
// Step 1: Build the Trie
public void addKeyword(String keyword) {
TrieNode currentNode = root;
for (char c : keyword.toCharArray()) {
currentNode = currentNode.children.computeIfAbsent(c, k -> new TrieNode());
}
currentNode.output.add(keyword);
}
// Step 2: Build Failure Links
public void buildFailureLinks() {
Queue<TrieNode> queue = new LinkedList<>();
root.failureLink = root;
queue.add(root);
while (!queue.isEmpty()) {
TrieNode current = queue.poll();
for (Map.Entry<Character, TrieNode> entry : current.children.entrySet()) {
char c = entry.getKey();
TrieNode child = entry.getValue();
// Set failure link
TrieNode failure = current.failureLink;
while (failure != root && !failure.children.containsKey(c)) {
failure = failure.failureLink;
}
if (failure.children.containsKey(c) && failure.children.get(c) != child) {
child.failureLink = failure.children.get(c);
} else {
child.failureLink = root;
}
// Merge output from failure link
child.output.addAll(child.failureLink.output);
queue.add(child);
}
}
}
// Step 3: Search the Text
public List<String> search(String text) {
List<String> results = new ArrayList<>();
TrieNode currentNode = root;
for (char c : text.toCharArray()) {
while (currentNode != root && !currentNode.children.containsKey(c)) {
currentNode = currentNode.failureLink;
}
if (currentNode.children.containsKey(c)) {
currentNode = currentNode.children.get(c);
}
// Add matches to results
results.addAll(currentNode.output);
}
return results;
}
public static void main(String[] args) {
AhoCorasick ac = new AhoCorasick();
ac.addKeyword("he");
ac.addKeyword("she");
ac.addKeyword("hers");
ac.addKeyword("his");
ac.buildFailureLinks();
List<String> matches = ac.search("ushers");
System.out.println("Matches found: " + matches);
}
}