1+ package com .thealgorithms .strings ;
2+
3+ /**
4+ * Z Algorithm for Pattern Matching
5+ *
6+ * The Z algorithm finds all occurrences of a pattern in a text in linear time.
7+ * For a string S of length n, the Z array stores the length of the longest substring
8+ * starting from S[i] which is also a prefix of S.
9+ *
10+ * Time Complexity: O(n + m) where n is text length and m is pattern length
11+ * Space Complexity: O(n + m)
12+ *
13+ * Applications:
14+ * - Pattern matching
15+ * - String searching
16+ * - Preprocessing for other string algorithms
17+ *
18+ * @author YourName
19+ */
20+ public final class ZAlgorithm {
21+
22+ private ZAlgorithm () {
23+ // Utility class
24+ }
25+
26+ /**
27+ * Computes the Z array for given string
28+ * Z[i] = length of longest substring starting from i which is also prefix of string
29+ *
30+ * @param str input string
31+ * @return Z array
32+ */
33+ public static int [] computeZArray (String str ) {
34+ if (str == null || str .isEmpty ()) {
35+ return new int [0 ];
36+ }
37+
38+ int n = str .length ();
39+ int [] z = new int [n ];
40+ z [0 ] = n ; // First element is always equal to string length
41+
42+ int left = 0 ;
43+ int right = 0 ;
44+
45+ for (int i = 1 ; i < n ; i ++) {
46+ if (i > right ) {
47+ // Outside the current Z-box, compute from scratch
48+ left = right = i ;
49+ while (right < n && str .charAt (right - left ) == str .charAt (right )) {
50+ right ++;
51+ }
52+ z [i ] = right - left ;
53+ right --;
54+ } else {
55+ // Inside the Z-box, use previously computed values
56+ int k = i - left ;
57+ if (z [k ] < right - i + 1 ) {
58+ z [i ] = z [k ];
59+ } else {
60+ left = i ;
61+ while (right < n && str .charAt (right - left ) == str .charAt (right )) {
62+ right ++;
63+ }
64+ z [i ] = right - left ;
65+ right --;
66+ }
67+ }
68+ }
69+
70+ return z ;
71+ }
72+
73+ /**
74+ * Searches for all occurrences of pattern in text using Z algorithm
75+ *
76+ * @param text the text to search in
77+ * @param pattern the pattern to search for
78+ * @return array of starting indices where pattern is found
79+ */
80+ public static int [] search (String text , String pattern ) {
81+ if (text == null || pattern == null || pattern .isEmpty () || text .length () < pattern .length ()) {
82+ return new int [0 ];
83+ }
84+
85+ // Concatenate pattern and text with a separator
86+ String concat = pattern + "$" + text ;
87+ int [] z = computeZArray (concat );
88+
89+ int patternLen = pattern .length ();
90+ java .util .List <Integer > results = new java .util .ArrayList <>();
91+
92+ // Find positions where Z value equals pattern length
93+ for (int i = patternLen + 1 ; i < z .length ; i ++) {
94+ if (z [i ] == patternLen ) {
95+ results .add (i - patternLen - 1 );
96+ }
97+ }
98+
99+ return results .stream ().mapToInt (Integer ::intValue ).toArray ();
100+ }
101+
102+ /**
103+ * Main method for testing
104+ */
105+ public static void main (String [] args ) {
106+ // Test Z array computation
107+ String str = "aabcaabxaaaz" ;
108+ int [] z = computeZArray (str );
109+ System .out .println ("Z array for '" + str + "':" );
110+ for (int i = 0 ; i < z .length ; i ++) {
111+ System .out .print (z [i ] + " " );
112+ }
113+ System .out .println ("\n " );
114+
115+ // Test pattern matching
116+ String text = "ababcabcabababd" ;
117+ String pattern = "ababd" ;
118+ int [] matches = search (text , pattern );
119+
120+ System .out .println ("Searching for '" + pattern + "' in '" + text + "'" );
121+ System .out .println ("Pattern found at indices: " );
122+ for (int index : matches ) {
123+ System .out .print (index + " " );
124+ }
125+ }
126+ }
0 commit comments