// O(n^2) solution
  public static int checkAns(ArrayList<String> A, ArrayList<String> Q) {
    HashSet<String> dict = new HashSet<String>();
    for (String s : Q) {
      dict.add(s);
    }

    Pair<Integer, Integer> ans = new Pair<Integer, Integer>(0, A.size() - 1);
    for (int l = 0; l < A.size(); ++l) {
      HashMap<String, Integer> count = new HashMap<String, Integer>();
      for (int r = l; r < A.size() && r - l < ans.getSecond() - ans.getFirst(); ++r) {
        if (dict.contains(A.get(r))) {
          count.put(A.get(r), count.containsKey(A.get(r)) ? count.get(A.get(r)) + 1 : 1);
        }
        if (count.size() == Q.size()) {
          if (r - l < ans.getSecond() - ans.getFirst()) {
            ans.setFirst(l);
            ans.setSecond(r);
          }
          break;
        }
      }
      count.clear();
    }

    return ans.getSecond() - ans.getFirst();
  }
  // @include
  public static Pair<Integer, Integer> findSmallestSubarrayCoveringSubset(
      ArrayList<String> A, ArrayList<String> Q) {
    HashSet<String> dict = new HashSet<String>(Q);
    HashMap<String, Integer> countQ = new HashMap<String, Integer>();
    int l = 0, r = 0;
    Pair<Integer, Integer> res = new Pair<Integer, Integer>(-1, -1);
    while (r < A.size()) {
      // Keep moving r until it reaches end or countQ has |Q| items.
      while (r < A.size() && countQ.size() < Q.size()) {
        if (dict.contains(A.get(r))) {
          countQ.put(A.get(r), countQ.containsKey(A.get(r)) ? countQ.get(A.get(r)) + 1 : 1);
        }
        ++r;
      }

      if (countQ.size() == Q.size()
          && // found |Q| keywords.
          ((res.getFirst() == -1 && res.getSecond() == -1)
              || r - 1 - l < res.getSecond() - res.getFirst())) {
        res.setFirst(l);
        res.setSecond(r - 1);
      }

      // Keep moving l until it reaches end or countQ has less |Q| items.
      while (l < r && countQ.size() == Q.size()) {
        if (dict.contains(A.get(l))) {
          int it = countQ.get(A.get(l));
          countQ.put(A.get(l), --it);
          if (it == 0) {
            countQ.remove(A.get(l));
            if ((res.getFirst() == -1 && res.getSecond() == -1)
                || r - 1 - l < res.getSecond() - res.getFirst()) {
              res.setFirst(l);
              res.setSecond(r - 1);
            }
          }
        }
        ++l;
      }
    }
    return res;
  }