-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAnalysis.java
More file actions
314 lines (261 loc) · 7.99 KB
/
Copy pathAnalysis.java
File metadata and controls
314 lines (261 loc) · 7.99 KB
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
class Naive extends Solution {
static {
SUBCLASSES.add(Naive.class);
System.out.println("Naive registered");
}
public Naive() {
}
@Override
public String Solve(String text, String pattern) {
List<Integer> indices = new ArrayList<>();
int n = text.length();
int m = pattern.length();
for (int i = 0; i <= n - m; i++) {
int j;
for (j = 0; j < m; j++) {
if (text.charAt(i + j) != pattern.charAt(j)) {
break;
}
}
if (j == m) {
indices.add(i);
}
}
return indicesToString(indices);
}
}
class KMP extends Solution {
static {
SUBCLASSES.add(KMP.class);
System.out.println("KMP registered");
}
public KMP() {
}
@Override
public String Solve(String text, String pattern) {
List<Integer> indices = new ArrayList<>();
int n = text.length();
int m = pattern.length();
// Handle empty pattern - matches at every position
if (m == 0) {
for (int i = 0; i <= n; i++) {
indices.add(i);
}
return indicesToString(indices);
}
// Compute LPS (Longest Proper Prefix which is also Suffix) array
int[] lps = computeLPS(pattern);
int i = 0; // index for text
int j = 0; // index for pattern
while (i < n) {
if (text.charAt(i) == pattern.charAt(j)) {
i++;
j++;
}
if (j == m) {
indices.add(i - j);
j = lps[j - 1];
} else if (i < n && text.charAt(i) != pattern.charAt(j)) {
if (j != 0) {
j = lps[j - 1];
} else {
i++;
}
}
}
return indicesToString(indices);
}
private int[] computeLPS(String pattern) {
int m = pattern.length();
int[] lps = new int[m];
int len = 0;
int i = 1;
lps[0] = 0;
while (i < m) {
if (pattern.charAt(i) == pattern.charAt(len)) {
len++;
lps[i] = len;
i++;
} else {
if (len != 0) {
len = lps[len - 1];
} else {
lps[i] = 0;
i++;
}
}
}
return lps;
}
}
class RabinKarp extends Solution {
static {
SUBCLASSES.add(RabinKarp.class);
System.out.println("RabinKarp registered.");
}
public RabinKarp() {
}
private static final int PRIME = 101; // A prime number for hashing
@Override
public String Solve(String text, String pattern) {
List<Integer> indices = new ArrayList<>();
int n = text.length();
int m = pattern.length();
// Handle empty pattern - matches at every position
if (m == 0) {
for (int i = 0; i <= n; i++) {
indices.add(i);
}
return indicesToString(indices);
}
if (m > n) {
return "";
}
int d = 256; // Number of characters in the input alphabet
long patternHash = 0;
long textHash = 0;
long h = 1;
// Calculate h = d^(m-1) % PRIME
for (int i = 0; i < m - 1; i++) {
h = (h * d) % PRIME;
}
// Calculate hash value for pattern and first window of text
for (int i = 0; i < m; i++) {
patternHash = (d * patternHash + pattern.charAt(i)) % PRIME;
textHash = (d * textHash + text.charAt(i)) % PRIME;
}
// Slide the pattern over text one by one
for (int i = 0; i <= n - m; i++) {
// Check if hash values match
if (patternHash == textHash) {
// Check characters one by one
boolean match = true;
for (int j = 0; j < m; j++) {
if (text.charAt(i + j) != pattern.charAt(j)) {
match = false;
break;
}
}
if (match) {
indices.add(i);
}
}
// Calculate hash value for next window
if (i < n - m) {
textHash = (d * (textHash - text.charAt(i) * h) + text.charAt(i + m)) % PRIME;
// Convert negative hash to positive
if (textHash < 0) {
textHash = textHash + PRIME;
}
}
}
return indicesToString(indices);
}
}
/**
* Boyer-Moore Implementation (Optimized with HashMap)
*/
class BoyerMoore extends Solution {
static {
SUBCLASSES.add(BoyerMoore.class);
System.out.println("BoyerMoore registered");
}
public BoyerMoore() {
}
@Override
public String Solve(String text, String pattern) {
List<Integer> matches = new ArrayList<>();
int n = text.length();
int m = pattern.length();
// Edge Case: Empty Pattern matches everywhere
if (m == 0) {
for (int i = 0; i <= n; i++) {
matches.add(i);
}
return indicesToString(matches);
}
// Pre-Processing: Bad Character Heuristic with HashMap
Map<Character, Integer> badChar = new HashMap<>();
for (int i = 0; i < m; i++) {
badChar.put(pattern.charAt(i), i);
}
// Searching Phase
int s = 0;
while (s <= (n - m)) {
int j = m - 1;
while (j >= 0 && pattern.charAt(j) == text.charAt(s + j)) {
j--;
}
if (j < 0) {
matches.add(s);
if (s + m < n) {
char nextChar = text.charAt(s + m);
int shift = badChar.getOrDefault(nextChar, -1);
s += m - shift;
} else {
s += 1;
}
} else {
char badCharInText = text.charAt(s + j);
int shift = badChar.getOrDefault(badCharInText, -1);
s += Math.max(1, j - shift);
}
}
return indicesToString(matches);
}
}
/**
* GoCrazy Implementation (Sunday's Algorithm - Optimized with HashMap)
*/
class GoCrazy extends Solution {
static {
SUBCLASSES.add(GoCrazy.class);
System.out.println("GoCrazy registered (Implementing Sunday's Algorithm)");
}
public GoCrazy() {
}
@Override
public String Solve(String text, String pattern) {
List<Integer> matches = new ArrayList<>();
int n = text.length();
int m = pattern.length();
// Edge Case: Empty Pattern matches everywhere
if (m == 0) {
for (int i = 0; i <= n; i++) {
matches.add(i);
}
return indicesToString(matches);
}
if (m > n) {
return indicesToString(matches);
}
// Pre-Processing: Sunday's Algorithm Shift Table with HashMap
Map<Character, Integer> shiftTable = new HashMap<>();
for (int i = 0; i < m; i++) {
shiftTable.put(pattern.charAt(i), m - i);
}
// Searching Phase
int s = 0;
while (s <= n - m) {
int j = 0;
while (j < m && text.charAt(s + j) == pattern.charAt(j)) {
j++;
}
if (j == m) {
matches.add(s);
}
// Shift Strategy (Sunday's Algorithm)
if (s + m < n) {
char nextChar = text.charAt(s + m);
s += shiftTable.getOrDefault(nextChar, m + 1);
} else {
break;
}
}
return indicesToString(matches);
}
}