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

Code before:
                    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);
                }
            }
        }
    }

    // method to search for patterns in text
    public static Map<String, ArrayList<Integer>> search(String text, String[] patterns) {
        Trie trie = new AhoCorasick().new Trie(patterns);
        ArrayList<ArrayList<Integer>> positionByStringIndexValue = trie.searchIn(text);
        return convert(positionByStringIndexValue, patterns);
    }

    // method for converting results to a map
    private static Map<String, ArrayList<Integer>> convert(ArrayList<ArrayList<Integer>> positionByStringIndexValue, String[] patterns) {
        Map<String, ArrayList<Integer>> positionByString = new HashMap<>();
        for (int i = 0; i < patterns.length; i++) {
            String pattern = patterns[i];
            ArrayList<Integer> positions = positionByStringIndexValue.get(i);
            positionByString.put(pattern, new ArrayList<>(positions));
        }
        return positionByString;
    }
}


Review comment (suggestion):
This is a very strange construction. Making the _nested_ classes `static`, will allow to do that:
```suggestion
        final var trie = new Trie(patterns);

```

Code after:

        // 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.
         *
         * @param parent The current node representing a character in the pattern trie.
         * @param currentPosition      The current position in the input text.
         */
        public void recordPatternPositions(final Node parent, final int currentPosition) {
            // Check if the current node represents the end of a pattern
            if (parent.getPatternInd() > -1) {
                // Add the current position to the list of positions for the found pattern
                positionByStringIndexValue.get(parent.getPatternInd()).add(currentPosition);
            }

            Node outputLink = parent.getOutputLink();
            // Follow output links to find and record positions of other patterns
            while (outputLink != null) {
                // Add the current position to the list of positions for the pattern linked by outputLink
                positionByStringIndexValue.get(outputLink.getPatternInd()).add(currentPosition);
                outputLink = outputLink.getOutputLink();
            }
        }
    }
    // method to search for patterns in text
    public static Map<String, ArrayList<Integer>> search(final String text, final String[] patterns) {
        final var trie = new Trie(patterns);
        final var positionByStringIndexValue = trie.searchIn(text);
        return convert(positionByStringIndexValue, patterns);
    }