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

Code before:
                        res.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)) {
                        i--; // Decrement i to reprocess the same character
                    }
                }
            }
            setUpStartPoints(res);
            return res;
        }
        // by default res contains end-points. This function converts those
        // endpoints to start points
        private void setUpStartPoints(ArrayList<ArrayList<Integer>> res) {
            for (int i = 0; i < patterns.length; i++) {
                if (!res.get(i).isEmpty()) {
                    for (int j = 0; j < res.get(i).size(); j++) {
                        int endpoint = res.get(i).get(j);
                        res.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>> res = trie.searchIn(text);
        return convert(res, patterns);
    }

    // method for converting results to a map
    private static Map<String, ArrayList<Integer>> convert(ArrayList<ArrayList<Integer>> res, String[] patterns) {
        Map<String, ArrayList<Integer>> positionByString = new HashMap<>();
        for (int i = 0; i < patterns.length; i++) {
            String pattern = patterns[i];
            ArrayList<Integer> positions = res.get(i);
            positionByString.put(pattern, new ArrayList<>(positions));
        }
        return positionByString;
    }
}


Review comment (suggestion):
I think this `if` statement is not needed here. If it would be `false`, then the loop has length 0 and nothing happens anyway.
```suggestion
                for (int j = 0; j < res.get(i).size(); j++) {
                    int endpoint = res.get(i).get(j);
                    res.get(i).set(j, endpoint - patterns[i].length() + 1);
                }
```

Code after:
        // 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);
    }

    // method for converting results to a map