code: private ArrayList<String> getUrlPartitions(String prefix) {
      ArrayList<String> expanded = new ArrayList<>();
      //The page prefix is case insensitive, A-Z is not necessary.
      for (char c = 'a'; c <= 'z'; ++c) {
        expanded.add(prefix + c);
      }
      for (int num = 0; num <= 9; ++num) {
        expanded.add(prefix + num);
      }
      expanded.add(prefix + "-");
      expanded.add(prefix + ".");
      expanded.add(prefix + "_"); //most important
      expanded.add(prefix + "~");
  
      expanded.add(prefix + "/"); //most important
      expanded.add(prefix + "%"); //most important
      expanded.add(prefix + ":");
      expanded.add(prefix + "?");
      expanded.add(prefix + "#");
      expanded.add(prefix + "@");
      expanded.add(prefix + "!");
      expanded.add(prefix + "$");
      expanded.add(prefix + "&");
      expanded.add(prefix + "+");
      expanded.add(prefix + "*");
      expanded.add(prefix + "'");
      expanded.add(prefix + "=");
      return expanded;
    }
docs: This doesn't cover all cases but more than 99.9% captured.
  
  According to the standard (RFC-3986), here are possible characters:
  unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
  reserved      = gen-delims / sub-delims
  gen-delims    = ":" / "/" / "?" / "#" / "[" / "]" / "@"
  sub-delims    = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
  
  
  Not included:
  reserved      = gen-delims / sub-delims
  gen-delims    = "[" / "]"
  sub-delims    = "(" / ")" / "," / ";"