Repository: TheAlgorithms/Java
File: src/main/java/com/thealgorithms/strings/AhoCorasick.java (Java)

Code before:
        obj.buildSuffixAndOutputLinks();

        ArrayList<ArrayList<Integer>> res = obj.search(text);
        ArrayList<Integer> countOfWords = obj.getRepeatCountOfWords();

        System.out.println("Using Zero Based Indexing");
        System.out.println("Dictonary is : ");
        for (int i = 0; i < patterns.length; i++) {
            System.out.println(i + ". " + patterns[i]);
        }
        System.out.println();
        System.out.println("Given text is : " + text);
        System.out.println();
        System.out.println("-1 represents word is not in the given string");
        for (int i = 0; i < patterns.length; i++) {
            System.out.print(patterns[i] + " appeared " + countOfWords.get(i) + " times at indices : ");
            if (res.get(i).isEmpty()) {
                System.out.print(-1 + " ");
            } else {
                for (int endpoint : res.get(i)) {
                    System.out.print((endpoint - patterns[i].length() + 1) + " ");
                }
            }
            System.out.println();
        }
    }
}


Review comment (suggestion):
Please remove the `main` method and instead add some proper tests. Good examples to look at:
- [`Factorial`](https://github.com/TheAlgorithms/Java/blob/566c27a996f48a94916170c159ae735546b39c42/src/main/java/com/thealgorithms/maths/Factorial.java) and [`FactorialTest`](https://github.com/TheAlgorithms/Java/blob/566c27a996f48a94916170c159ae735546b39c42/src/test/java/com/thealgorithms/maths/FactorialTest.java),
- [`FindMax`](https://github.com/TheAlgorithms/Java/blob/566c27a996f48a94916170c159ae735546b39c42/src/main/java/com/thealgorithms/maths/FindMax.java) and [`FindMaxTest`](https://github.com/TheAlgorithms/Java/blob/566c27a996f48a94916170c159ae735546b39c42/src/test/java/com/thealgorithms/maths/FindMaxTest.java).

```suggestion
```

Code after:
            var positionByStringIndexValue = initializePositionByStringIndexValue(); // Initialize a list to store positions of the current pattern
            Node parent = root; // Start searching from the root node

            PatternPositionRecorder positionRecorder = new PatternPositionRecorder(positionByStringIndexValue);

            for (int i = 0; i < text.length(); i++) {
                char ch = text.charAt(i); // Get the current character in the text

                // Check if the current node has a child for the current character
                if (parent.getChild().containsKey(ch)) {
                    parent = parent.getChild().get(ch); // Update the current node to the child node
                    positionRecorder.recordPatternPositions(parent, i); // Use the method in PatternPositionRecorder to record positions
                } else {
                    // If no child node exists for the character, backtrack using suffix links
                    while (parent != root && !parent.getChild().containsKey(ch)) {
                        parent = parent.getSuffixLink();
                    }
                    if (parent.getChild().containsKey(ch)) {
                        i--; // Decrement i to reprocess the same character
                    }
                }
            }

            setUpStartPoints(positionByStringIndexValue);
            return positionByStringIndexValue;
        }

        // by default positionByStringIndexValue contains end-points. This function converts those
        // endpoints to start points
        private void setUpStartPoints(ArrayList<ArrayList<Integer>> positionByStringIndexValue) {
            for (int i = 0; i < patterns.length; i++) {
                for (int j = 0; j < positionByStringIndexValue.get(i).size(); j++) {
                    int endpoint = positionByStringIndexValue.get(i).get(j);
                    positionByStringIndexValue.get(i).set(j, endpoint - patterns[i].length() + 1);
                }
            }
        }
    }

    // Class to handle pattern position recording
    private static class PatternPositionRecorder {
        private ArrayList<ArrayList<Integer>> positionByStringIndexValue;

        // Constructor to initialize the recorder with the position list
        PatternPositionRecorder(final ArrayList<ArrayList<Integer>> positionByStringIndexValue) {
            this.positionByStringIndexValue = positionByStringIndexValue;
        }

        /**
         * Records positions for a pattern when it's found in the input text and follows
         * output links to record positions of other patterns.