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

Code before:
                // Establish output links for nodes to efficiently identify patterns within patterns
                if (currentState.getSuffixLink().getPatternInd() >= 0) {
                    currentState.setOutputLink(currentState.getSuffixLink());
                } else {
                    currentState.setOutputLink(currentState.getSuffixLink().getOutputLink());
                }
            }
        }

        // Searches for patterns in the input text and records their positions
        public ArrayList<ArrayList<Integer>> searchIn(String text) {
            /*
             * positionByStringIndexValue is the list of list containing the indexes of words in patterns/dictionary
             * list index represents word.
             * eg - list[0] contains the list of start-index of word pattern[0]
             *      list[1] contains the list of start-index of word pattern[1]
             *      ......
             *      ......
             *      list[n] contains the list of start-index of word pattern[n]
             */
            ArrayList<ArrayList<Integer>> positionByStringIndexValue = new ArrayList<>(patterns.length); // Stores positions where patterns are found in the text
            Node parent = root; // Start searching from the root node

            for (int i = 0; i < patterns.length; i++) {
                positionByStringIndexValue.add(new ArrayList<Integer>()); // Initialize a list to store positions of the current pattern
            }

            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

                    // If the current node represents a pattern, record its position in positionByStringIndexValue
                    if (parent.getPatternInd() > -1) {
                        positionByStringIndexValue.get(parent.getPatternInd()).add(i);
                    }

                    Node outputLink = parent.getOutputLink();
                    // Follow output links to find and record positions of other patterns
                    while (outputLink != null) {
                        positionByStringIndexValue.get(outputLink.getPatternInd()).add(i);
                        outputLink = outputLink.getOutputLink();
                    }
                } 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)) {

Review comment (suggestion):
```suggestion
            var positionByStringIndexValue = initializePositionByStringIndexValue(patterns.length); // Stores positions where patterns are found in the text
            Node parent = root; // Start searching from the root node
```

Code after:
                }

                // Establish output links for nodes to efficiently identify patterns within patterns
                if (currentState.getSuffixLink().getPatternInd() >= 0) {
                    currentState.setOutputLink(currentState.getSuffixLink());
                } else {
                    currentState.setOutputLink(currentState.getSuffixLink().getOutputLink());
                }
            }
        }

        private ArrayList<ArrayList<Integer>> initializePositionByStringIndexValue() {
            ArrayList<ArrayList<Integer>> positionByStringIndexValue = new ArrayList<>(patterns.length); // Stores positions where patterns are found in the text
            for (int i = 0; i < patterns.length; i++) {
                positionByStringIndexValue.add(new ArrayList<Integer>());
            }
            return positionByStringIndexValue;
        }

        // Searches for patterns in the input text and records their positions
        public ArrayList<ArrayList<Integer>> searchIn(final String text) {
            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) {