// Source : https://leetcode.com/problems/compare-strings-by-frequency-of-the-smallest-character/
// Author : Hao Chen
// Date   : 2019-10-01

/***************************************************************************************************** 
 *
 * Let's define a function f(s) over a non-empty string s, which calculates the frequency of the 
 * smallest character in s. For example, if s = "dcce" then f(s) = 2 because the smallest character is 
 * "c" and its frequency is 2.
 * 
 * Now, given string arrays queries and words, return an integer array answer, where each answer[i] is 
 * the number of words such that f(queries[i]) < f(W), where W is a word in words.
 * 
 * Example 1:
 * 
 * Input: queries = ["cbd"], words = ["zaaaz"]
 * Output: [1]
 * Explanation: On the first query we have f("cbd") = 1, f("zaaaz") = 3 so f("cbd") < f("zaaaz").
 * 
 * Example 2:
 * 
 * Input: queries = ["bbb","cc"], words = ["a","aa","aaa","aaaa"]
 * Output: [1,2]
 * Explanation: On the first query only f("bbb") < f("aaaa"). On the second query both f("aaa") and 
 * f("aaaa") are both > f("cc").
 * 
 * Constraints:
 * 
 * 	1 <= queries.length <= 2000
 * 	1 <= words.length <= 2000
 * 	1 <= queries[i].length, words[i].length <= 10
 * 	queries[i][j], words[i][j] are English lowercase letters.
 ******************************************************************************************************/

class Solution {
public:
    vector<int> numSmallerByFrequency(vector<string>& queries, vector<string>& words) {
        cout << queries.size() << " : " << words.size() << endl;
        vector<int> freq;
        for (auto w : words) {
            freq.push_back(f(w));
        }
        sort(freq.begin(), freq.end());

        vector<int> result;
        for (auto q : queries) {
            result.push_back(binary_search(freq, f(q)));
        }
        return result;
    }

    int f(string& s) {
        char ch = 'z' + 1; //stroe the smallest char
        int cnt = 0;  //stroe the frequency of the smallest char
        for (auto c : s) {
            if (c < ch) { //find the smaller char, reset the count
                cnt  = 1;
                ch = c;
            } if (c == ch) {
                cnt++;
            }
        }
        return cnt;
    }

    int binary_search(vector<int> &v, int target) {
        int low=0, high=v.size()-1, mid;

        while (low < high) {
            mid = low + (high - low) / 2;
            if ( v[mid] > target) {
                high = mid -1;
            } else if (v[mid] <= target) {
                low = mid + 1;
            }
        }

        low = v[low] > target  ? low : low + 1;

        return v.size() - low;
    }

};