Skip to content

Z Algorithm #5959

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 17 commits into from
60 changes: 60 additions & 0 deletions src/main/java/com/thealgorithms/strings/Zalgorithm.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.thealgorithms.strings;

import java.util.ArrayList;
import java.util.List;

/**
* Z-algorithm implementation to find all occurrences of a pattern in a text.
*/
public final class Zalgorithm {
private Zalgorithm() {
}

/**
* Finds the occurrences of a pattern in a text using Z-algorithm.
*
* @param text the input text in which we are searching the pattern
* @param pattern the pattern to search for
* @return a list of indices where the pattern occurs in the text
*/
public static List<Integer> findPatternOccurrences(String text, String pattern) {
String combined = pattern + "$" + text;
int[] zArray = calculateZ(combined);
List<Integer> occurrences = new ArrayList<>();
int patternLength = pattern.length();

for (int i = 0; i < zArray.length; i++) {
if (zArray[i] == patternLength) {
occurrences.add(i - patternLength - 1);
}
}
return occurrences;
}

/**
* Helper method to calculate Z-array for a given string.
*
* @param s the input string
* @return the Z-array where Z[i] is the length of the longest substring
* starting from i that is also a prefix of s
*/
private static int[] calculateZ(String s) {
int n = s.length();
int[] z = new int[n];
int l = 0, r = 0;

for (int i = 1; i < n; i++) {
if (i <= r) {
z[i] = Math.min(r - i + 1, z[i - l]);
}
while (i + z[i] < n && s.charAt(z[i]) == s.charAt(i + z[i])) {
z[i]++;
}
if (i + z[i] - 1 > r) {
l = i;
r = i + z[i] - 1;
}
}
return z;
}
}
48 changes: 48 additions & 0 deletions src/test/java/com/thealgorithms/strings/ZalgorithmTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.thealgorithms.strings;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.Arrays;
import java.util.List;
import org.junit.jupiter.api.Test;

public class ZalgorithmTest {

/**
* Test 1:
* Pattern: "a", Text: "aabaaabaa"
* Expected: [0, 1, 4, 5, 8]
*/
@Test
public void testFindPatternOccurrencesSingleCharacter() {
String text = "aabaaabaa";
String pattern = "a";
List<Integer> expected = Arrays.asList(0, 1, 4, 5, 8);
assertEquals(expected, Zalgorithm.findPatternOccurrences(text, pattern));
}

/**
* Test 2:
* Pattern: "abc", Text: "ababcabcabc"
* Expected: [2, 5, 8]
*/
@Test
public void testFindPatternOccurrences() {
String text = "ababcabcabc";
String pattern = "abc";
List<Integer> expected = Arrays.asList(2, 5, 8);
assertEquals(expected, Zalgorithm.findPatternOccurrences(text, pattern));
}
/**
* Test 3:
* Pattern: "aa", Text: "aaaaaa"
* Expected: [0, 1, 2, 3, 4]
*/
@Test
public void testFindPatternOccurrencesRepeated() {
String text = "aaaaaa";
String pattern = "aa";
List<Integer> expected = Arrays.asList(0, 1, 2, 3, 4);
assertEquals(expected, Zalgorithm.findPatternOccurrences(text, pattern));
}
}
Loading