Skip to content

Commit 7d13207

Browse files
author
Samuel Facchinello
committed
refactor
1 parent 3ecd135 commit 7d13207

File tree

1 file changed

+78
-40
lines changed

1 file changed

+78
-40
lines changed
Lines changed: 78 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,118 @@
11
package com.thealgorithms.others;
22

3-
/**
4-
* @author Prateek Kumar Oraon (https://github.com/prateekKrOraon)
5-
*/
63
import java.util.Scanner;
4+
import java.util.Set;
5+
import java.util.TreeSet;
76

8-
// An implementation of string matching using finite automata
7+
/**
8+
* A class to perform string matching using <a href="https://en.wikipedia.org/wiki/Finite-state_machine">finite automata</a>.
9+
*
10+
* @author <a href="https://github.com/prateekKrOraon">Prateek Kumar Oraon</a>
11+
*/
912
public final class StringMatchFiniteAutomata {
13+
14+
// Constants
15+
private static final int CHARS = 256; // Total number of characters in the input alphabet
16+
17+
// Finite automata table
18+
private static int[][] finiteAutomata;
19+
20+
// Private constructor to prevent instantiation
1021
private StringMatchFiniteAutomata() {
1122
}
1223

13-
public static final int CHARS = 256;
14-
public static int[][] fa;
15-
public static Scanner scanner = null;
16-
1724
public static void main(String[] args) {
18-
scanner = new Scanner(System.in);
19-
System.out.println("Enter String");
20-
String text = scanner.nextLine();
21-
System.out.println("Enter pattern");
22-
String pat = scanner.nextLine();
25+
// Scanner instance for user input
26+
try (Scanner scanner = new Scanner(System.in);) {
27+
28+
System.out.println("Enter text:");
29+
String text = scanner.nextLine();
2330

24-
searchPat(text, pat);
31+
System.out.println("Enter pattern:");
32+
String pattern = scanner.nextLine();
2533

26-
scanner.close();
34+
Set<Integer> indexFound = searchPattern(text, pattern);
35+
indexFound.forEach(System.out::println);
36+
}
2737
}
2838

29-
public static void searchPat(String text, String pat) {
30-
int m = pat.length();
31-
int n = text.length();
39+
/**
40+
* Searches for the pattern in the given text using finite automata.
41+
*
42+
* @param text The text to search within.
43+
* @param pattern The pattern to search for.
44+
*/
45+
public static Set<Integer> searchPattern(String text, String pattern) {
46+
Set<Integer> indexFound = new TreeSet<>();
47+
int patternLength = pattern.length();
48+
int textLength = text.length();
49+
50+
// Initialize finite automata table
51+
finiteAutomata = new int[patternLength + 1][CHARS];
3252

33-
fa = new int[m + 1][CHARS];
53+
// Preprocess the pattern to create the finite automata table
54+
computeFiniteAutomata(pattern, patternLength);
3455

35-
computeFA(pat, m, fa);
56+
int state = 0; // Initial state
3657

37-
int state = 0;
38-
for (int i = 0; i < n; i++) {
39-
state = fa[state][text.charAt(i)];
58+
// Process the text over the finite automata
59+
for (int i = 0; i < textLength; i++) {
60+
state = finiteAutomata[state][text.charAt(i)];
4061

41-
if (state == m) {
42-
System.out.println("Pattern found at index " + (i - m + 1));
62+
if (state == patternLength) {
63+
indexFound.add((i - patternLength + 1));
4364
}
4465
}
66+
return indexFound;
4567
}
4668

47-
// Computes finite automata for the pattern
48-
public static void computeFA(String pat, int m, int[][] fa) {
49-
for (int state = 0; state <= m; ++state) {
69+
/**
70+
* Computes the finite automata table for the given pattern.
71+
*
72+
* @param pattern The pattern to preprocess.
73+
* @param patternLength The length of the pattern.
74+
*/
75+
private static void computeFiniteAutomata(String pattern, int patternLength) {
76+
for (int state = 0; state <= patternLength; ++state) {
5077
for (int x = 0; x < CHARS; ++x) {
51-
fa[state][x] = getNextState(pat, m, state, x);
78+
finiteAutomata[state][x] = getNextState(pattern, patternLength, state, x);
5279
}
5380
}
5481
}
5582

56-
public static int getNextState(String pat, int m, int state, int x) {
57-
// if current state is less than length of pattern
58-
// and input character of pattern matches the character in the alphabet
59-
// then automata goes to next state
60-
if (state < m && x == pat.charAt(state)) {
83+
/**
84+
* Gets the next state for the finite automata.
85+
*
86+
* @param pattern The pattern being matched.
87+
* @param patternLength The length of the pattern.
88+
* @param state The current state.
89+
* @param x The current character from the input alphabet.
90+
* @return The next state.
91+
*/
92+
private static int getNextState(String pattern, int patternLength, int state, int x) {
93+
// If the current state is less than the length of the pattern
94+
// and the character matches the pattern character, go to the next state
95+
if (state < patternLength && x == pattern.charAt(state)) {
6196
return state + 1;
6297
}
6398

99+
// Check for the highest prefix which is also a suffix
64100
for (int ns = state; ns > 0; ns--) {
65-
if (pat.charAt(ns - 1) == x) {
101+
if (pattern.charAt(ns - 1) == x) {
102+
boolean match = true;
66103
for (int i = 0; i < ns - 1; i++) {
67-
if (pat.charAt(i) != pat.charAt(state - ns + i + 1)) {
104+
if (pattern.charAt(i) != pattern.charAt(state - ns + i + 1)) {
105+
match = false;
68106
break;
69107
}
70-
71-
if (i == ns - 1) {
72-
return ns;
73-
}
108+
}
109+
if (match) {
110+
return ns;
74111
}
75112
}
76113
}
77114

115+
// If no prefix which is also a suffix is found, return 0
78116
return 0;
79117
}
80118
}

0 commit comments

Comments
 (0)