@@ -13,9 +13,6 @@ public final class StringMatchFiniteAutomata {
13
13
// Constants
14
14
private static final int CHARS = 256 ; // Total number of characters in the input alphabet
15
15
16
- // Finite automata table
17
- private static int [][] finiteAutomata ;
18
-
19
16
// Private constructor to prevent instantiation
20
17
private StringMatchFiniteAutomata () {
21
18
}
@@ -26,25 +23,16 @@ private StringMatchFiniteAutomata() {
26
23
* @param text The text to search within.
27
24
* @param pattern The pattern to search for.
28
25
*/
29
- public static Set <Integer > searchPattern (String text , String pattern ) {
30
- Set <Integer > indexFound = new TreeSet <>();
31
- int patternLength = pattern .length ();
32
- int textLength = text .length ();
33
-
34
- // Initialize finite automata table
35
- finiteAutomata = new int [patternLength + 1 ][CHARS ];
36
-
37
- // Preprocess the pattern to create the finite automata table
38
- computeFiniteAutomata (pattern , patternLength );
39
-
40
- int state = 0 ; // Initial state
26
+ public static Set <Integer > searchPattern (final String text , final String pattern ) {
27
+ final var stateTransitionTable = computeStateTransitionTable (pattern );
28
+ FiniteAutomata finiteAutomata = new FiniteAutomata (stateTransitionTable );
41
29
42
- // Process the text over the finite automata
43
- for (int i = 0 ; i < textLength ; i ++) {
44
- state = finiteAutomata [ state ][ text .charAt (i )] ;
30
+ Set < Integer > indexFound = new TreeSet <>();
31
+ for (int i = 0 ; i < text . length () ; i ++) {
32
+ finiteAutomata . consume ( text .charAt (i )) ;
45
33
46
- if (state == patternLength ) {
47
- indexFound .add (i - patternLength + 1 );
34
+ if (finiteAutomata . getState () == pattern . length () ) {
35
+ indexFound .add (i - pattern . length () + 1 );
48
36
}
49
37
}
50
38
return indexFound ;
@@ -53,15 +41,20 @@ public static Set<Integer> searchPattern(String text, String pattern) {
53
41
/**
54
42
* Computes the finite automata table for the given pattern.
55
43
*
56
- * @param pattern The pattern to preprocess.
57
- * @param patternLength The length of the pattern .
44
+ * @param pattern The pattern to preprocess.
45
+ * @return The state transition table .
58
46
*/
59
- private static void computeFiniteAutomata (String pattern , int patternLength ) {
47
+ private static int [][] computeStateTransitionTable (final String pattern ) {
48
+ int patternLength = pattern .length ();
49
+ int [][] stateTransitionTable = new int [patternLength + 1 ][CHARS ];
50
+
60
51
for (int state = 0 ; state <= patternLength ; ++state ) {
61
52
for (int x = 0 ; x < CHARS ; ++x ) {
62
- finiteAutomata [state ][x ] = getNextState (pattern , patternLength , state , x );
53
+ stateTransitionTable [state ][x ] = getNextState (pattern , patternLength , state , x );
63
54
}
64
55
}
56
+
57
+ return stateTransitionTable ;
65
58
}
66
59
67
60
/**
@@ -73,7 +66,7 @@ private static void computeFiniteAutomata(String pattern, int patternLength) {
73
66
* @param x The current character from the input alphabet.
74
67
* @return The next state.
75
68
*/
76
- private static int getNextState (String pattern , int patternLength , int state , int x ) {
69
+ private static int getNextState (final String pattern , final int patternLength , final int state , final int x ) {
77
70
// If the current state is less than the length of the pattern
78
71
// and the character matches the pattern character, go to the next state
79
72
if (state < patternLength && x == pattern .charAt (state )) {
@@ -99,4 +92,35 @@ private static int getNextState(String pattern, int patternLength, int state, in
99
92
// If no prefix which is also a suffix is found, return 0
100
93
return 0 ;
101
94
}
95
+
96
+ /**
97
+ * A class representing the finite automata for pattern matching.
98
+ */
99
+ private static class FiniteAutomata {
100
+ private int state ;
101
+ private final int [][] stateTransitionTable ;
102
+
103
+ public FiniteAutomata (int [][] stateTransitionTable ) {
104
+ this .stateTransitionTable = stateTransitionTable ;
105
+ this .state = 0 ; // Initial state
106
+ }
107
+
108
+ /**
109
+ * Consumes an input character and transitions to the next state.
110
+ *
111
+ * @param input The input character.
112
+ */
113
+ public void consume (final char input ) {
114
+ state = stateTransitionTable [state ][input ];
115
+ }
116
+
117
+ /**
118
+ * Gets the current state of the finite automata.
119
+ *
120
+ * @return The current state.
121
+ */
122
+ public int getState () {
123
+ return state ;
124
+ }
125
+ }
102
126
}
0 commit comments