You are given a 0-indexed array of strings words and a 2D array of integers queries.
Each query queries[i] = [li, ri] asks us to find the number of strings present at the indices ranging from li to ri (both inclusive) of words that start and end with a vowel.
Return an array ans of size queries.length, where ans[i] is the answer to the ith query.
Note that the vowel letters are 'a', 'e', 'i', 'o', and 'u'.
Example 1:
Input: words = ["aba","bcb","ece","aa","e"], queries = [[0,2],[1,4],[1,1]]
Output: [2,3,0]
Explanation: The strings starting and ending with a vowel are "aba", "ece", "aa" and "e".
The answer to the query [0,2] is 2 (strings "aba" and "ece").
to query [1,4] is 3 (strings "ece", "aa", "e").
to query [1,1] is 0.
We return [2,3,0].
Example 2:
Input: words = ["a","e","i"], queries = [[0,2],[0,1],[2,2]]
Output: [3,2,1]
Explanation: Every string satisfies the conditions, so we return [3,2,1].
Constraints:
1 <= words.length <= 105
1 <= words[i].length <= 40
words[i] consists only of lowercase English letters.
sum(words[i].length) <= 3 * 105
1 <= queries.length <= 105
0 <= li <= ri < words.length
Solutions
Solution 1: Preprocessing + Binary Search
Thinking
Each query asks how many words in a range start and end with a vowel. Testing every word per query is too slow at \(n,q\le 10^5\).
Collect the qualifying indices in order. A query becomes a count of indices inside \([l,r]\), i.e. the difference of two binary searches.
We can preprocess all the indices of the strings that start and end with a vowel, and record them in order in the array \(nums\).
Next, we iterate through each query \((l, r)\), and use binary search to find the first index \(i\) in \(nums\) that is greater than or equal to \(l\), and the first index \(j\) that is greater than \(r\). Therefore, the answer to the current query is \(j - i\).
The time complexity is \(O(n + m \times \log n)\), and the space complexity is \(O(n)\). Where \(n\) and \(m\) are the lengths of the arrays \(words\) and \(queries\), respectively.
Solution 1 still costs a logarithm per query. A \(0/1\) prefix sum of the vowel-string indicator answers each range as \(s[r+1]-s[l]\) in constant time.
We can create a prefix sum array \(s\) of length \(n+1\), where \(s[i]\) represents the number of strings that start and end with a vowel in the first \(i\) strings of the array \(words\). Initially, \(s[0] = 0\).
Next, we iterate through the array \(words\). If the current string starts and ends with a vowel, then \(s[i+1] = s[i] + 1\), otherwise \(s[i+1] = s[i]\).
Finally, we iterate through each query \((l, r)\). Therefore, the answer to the current query is \(s[r+1] - s[l]\).
The time complexity is \(O(n + m)\), and the space complexity is \(O(n)\). Where \(n\) and \(m\) are the lengths of the arrays \(words\) and \(queries\), respectively.