Skip to content

Commit 095fa07

Browse files
committed
add ZAlgorithm for linear pattern matching
1 parent 5e9d9f7 commit 095fa07

File tree

2 files changed

+110
-0
lines changed

2 files changed

+110
-0
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package com.thealgorithms.strings;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
/**
7+
* Z Algorithm for pattern matching in linear time
8+
*
9+
* The Z-algorithm computes, for each position i in a string,
10+
* the length of the longest substring starting at i which is
11+
* also a prefix of the string.
12+
*
13+
* Time Complexity: O(n + m) where n is text length, m is pattern length
14+
* Space Complexity: O(n + m)
15+
*
16+
* @author Your Name
17+
*/
18+
public final class ZAlgorithm {
19+
private ZAlgorithm() {
20+
}
21+
22+
/**
23+
* Finds all occurrences of pattern in text using Z-algorithm
24+
*
25+
* @param text the text to search in
26+
* @param pattern the pattern to search for
27+
* @return list of starting indices where pattern occurs
28+
* @throws IllegalArgumentException if text or pattern is null
29+
*/
30+
public static List<Integer> search(String text, String pattern) {
31+
if (text == null || pattern == null) {
32+
throw new IllegalArgumentException("Text and pattern cannot be null");
33+
}
34+
35+
List<Integer> result = new ArrayList<>();
36+
37+
if (pattern.isEmpty() || pattern.length() > text.length()) {
38+
return result;
39+
}
40+
41+
// Concatenate pattern and text with a separator
42+
String combined = pattern + "$" + text;
43+
int[] zArray = computeZArray(combined);
44+
45+
int patternLength = pattern.length();
46+
47+
// Find positions where Z-value equals pattern length
48+
for (int i = patternLength + 1; i < combined.length(); i++) {
49+
if (zArray[i] == patternLength) {
50+
result.add(i - patternLength - 1);
51+
}
52+
}
53+
54+
return result;
55+
}
56+
57+
/**
58+
* Computes the Z-array for the given string
59+
* Z[i] = length of longest substring starting at i which is also a prefix
60+
*
61+
* @param str input string
62+
* @return Z-array
63+
*/
64+
private static int[] computeZArray(String str) {
65+
int n = str.length();
66+
int[] zArray = new int[n];
67+
68+
int left = 0;
69+
int right = 0;
70+
71+
for (int i = 1; i < n; i++) {
72+
if (i > right) {
73+
left = right = i;
74+
while (right < n && str.charAt(right - left) == str.charAt(right)) {
75+
right++;
76+
}
77+
zArray[i] = right - left;
78+
right--;
79+
} else {
80+
int k = i - left;
81+
if (zArray[k] < right - i + 1) {
82+
zArray[i] = zArray[k];
83+
} else {
84+
left = i;
85+
while (right < n && str.charAt(right - left) == str.charAt(right)) {
86+
right++;
87+
}
88+
zArray[i] = right - left;
89+
right--;
90+
}
91+
}
92+
}
93+
return zArray;
94+
}
95+
96+
/**
97+
* Computes only the Z-array for a given string
98+
* Useful for other applications beyond pattern matching
99+
*
100+
* @param str input string
101+
* @return Z-array where Z[i] is length of longest prefix match at position i
102+
* @throws IllegalArgumentException if string is null
103+
*/
104+
public static int[] getZArray(String str) {
105+
if (str == null) {
106+
throw new IllegalArgumentException("String cannot be null");
107+
}
108+
return computeZArray(str);
109+
}
110+
}

src/test/java/com/thealgorithms/strings/ZAlgorithmTest.java

Whitespace-only changes.

0 commit comments

Comments
 (0)