Problem Description
Given a 0-indexed string s and two patterns a and b, along with an integer k, find all starting indices i in s such that:
- s[i..(i + a.length - 1)] matches a.
- There exists an index j where s[j..(j + b.length - 1)] matches b and |i - j| <= k. Return the beautiful indices in sorted order.
Key Insights
- Precompute all starting indices in s where substring a appears.
- Precompute all starting indices in s where substring b appears.
- Both lists are naturally sorted by the order of appearance.
- For each index from the first list, use binary search on the second list to check if any index j exists with |i - j| <= k.
- This transforms the problem into efficiently querying ranges in a sorted list.
Space and Time Complexity
Time Complexity: O(n + m log m), where n is the length of s (for the two scans) and m is the number of occurrences of pattern b (used in binary search for each occurrence of a). Space Complexity: O(n) for storing the indices.
Solution
We first scan through s to collect all starting indices where the substring equals a and similarly for b. Then, for each index i in the a-occurrences, we perform a binary search on the sorted list of b-occurrences to find the smallest index j such that j is at least (i - k). We then check if the found j (or its predecessor) satisfies |i - j| <= k. This binary search step reduces the time required compared to a brute-force comparison, making the solution efficient even for large inputs.