import java.util.*;
import java.util.zip.*;
import java.util.List;
import java.util.regex.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.table.*;
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
import java.lang.ref.*;
import java.lang.management.*;
import java.security.*;
import java.security.spec.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.imageio.*;
import java.math.*;
class main {
static class DeepWordPairIndex {
boolean _isTransient() { return true; }
  String regexp = "\\w+";
  boolean useHashMaps = true; // makes it case-sensitive and doesn't allow partial word searches
  Map> entries = new HashMap();
  MultiSetMap, Entry> entriesByPair = new MultiSetMap();
  
  static class Entry extends Var {
    Map, int[]> pairPositions = new HashMap(); // int array is sorted
    
    Entry(A id) { super(id); }
  }
  
  void useHashMaps() {
    useHashMaps = true;
    entriesByPair = new MultiSetMap();
  }
  
  List wordRanges(String text) {
    return regexpFindRanges(regexp, text);
  }
   
  void add(A a, String text) {
    Entry e = new Entry(a);
    if (useHashMaps) {
      e.pairPositions = new HashMap();
      text = upper(text);
    }
    if (entries.put(a, e) != null) throw fail("Double insertion");
    MultiMap, Integer> pairPositions = new MultiMap();
    for (Pair p : overlappingPairs(wordRanges(text))) {
      Pair pair = pair(substring(text, p.a), substring(text, p.b));
      pairPositions.put(pair, p.a.start);
      entriesByPair.put(pair, e);
    }
    for (Pair pair : keys(pairPositions))
      e.pairPositions.put(pair, toIntArray(pairPositions.get(pair)));
  }
  
  Set> get(Pair pair) { return entriesByPair.get(pair); }
  
  int numPairs() { return entriesByPair.keysSize(); }
  
  Iterable>>lookupString_withPositions(String query, Object... __) {
    boolean debug = boolPar("debug",__);
    if (useHashMaps) query = upper(query);
    String _query = query;
    List ranges = wordRanges(query);
    if (empty(ranges)) return null;
    int nRanges = l(ranges);
    int iFirstComplete = first(ranges).start == 0 ? 1 : 0;
    int iLastComplete = last(ranges).end == l(query) ? nRanges-1 : nRanges;
    --iLastComplete; // because pairs
    
    List words = map(ranges, r -> substring(_query, r));
    List> pairs = overlappingPairs(words);
    List>> entriesAtIndex = map(pairs, pair -> entriesByPair.get(pair));
      
    if (iLastComplete >= iFirstComplete+1) {
      int shortest = iFirstComplete, nBest = l(entriesAtIndex.get(shortest));
      if (nBest == 0) return emptyList();
      for (int iWord = iFirstComplete+1; iWord < iLastComplete; iWord++) {
        int n = l(entriesAtIndex.get(iWord));
        if (n == 0) return emptyList();
        if (n < nBest) {
          shortest = iWord;
          nBest = n;
        }
      }
      
      /*if (debug)*/ print("pairs: " + zipTwoLists(pairs, lmap(__19 -> l(__19),entriesAtIndex)));
      
      Set> entries = entriesAtIndex.get(shortest);
      int startShortest = ranges.get(shortest).start;
      Pair shortestPair = pairs.get(shortest); // not the shortest pair, but the pair with the shortest result list
      IntBuffer intBuffer = new IntBuffer();
      
      List>> out = new ArrayList();
      entrySearch: for (Entry entry : entries) {
        int[] positions = entry.pairPositions.get(shortestPair);
        for (int iWord = iFirstComplete; iWord < iLastComplete; iWord++) {
          { if (iWord == shortest) continue; }
          IntRange r2 = ranges.get(iWord);
          Pair pair2 = pairs.get(iWord);
          int[] positions2 = entry.pairPositions.get(pair2);
          if (positions2 == null) continue entrySearch;
          int ofs = startShortest-r2.start;
          //if (debug) print("Intersecting " + asList(positions) + "/" + asList(positions2) + " with ofs " + ofs);
          positions = intersectSortedIntArrays_ofs_optimized2(positions, positions2, ofs, intBuffer);
          //if (debug) print("Got " + asList(positions));
          if (empty(positions)) continue entrySearch;
        }
        
        out.add(pair(entry.get(), wrapIntArrayAsImmutableList_ofs(positions, -startShortest)));
      }
      return out;
    }
    
    return null;
  }
}
static List regexpFindRanges(String pat, String s) {
  Matcher m = regexpMatcher(pat, s);
  List l = new ArrayList();
  while (m.find())
    l.add(new IntRange(m.start(), m.end()));
  return l;
}
static String upper(String s) {
  return s == null ? null : s.toUpperCase();
}
static char upper(char c) {
  return Character.toUpperCase(c);
}
static RuntimeException fail() { throw new RuntimeException("fail"); }
static RuntimeException fail(Throwable e) { throw asRuntimeException(e); }
static RuntimeException fail(Object msg) { throw new RuntimeException(String.valueOf(msg)); }
static RuntimeException fail(String msg) { throw new RuntimeException(msg == null ? "" : msg); }
static RuntimeException fail(String msg, Throwable innerException) { throw new RuntimeException(msg, innerException); }
static  List> overlappingPairs(List l) {
  return listToOverlappingPairs(l);
}
static  Pair pair(A a, B b) {
  return new Pair(a, b);
}
static  Pair pair(A a) {
  return new Pair(a, a);
}
static String substring(String s, int x) {
  return substring(s, x, strL(s));
}
static String substring(String s, int x, int y) {
  if (s == null) return null;
  if (x < 0) x = 0;
  if (x >= s.length()) return "";
  if (y < x) y = x;
  if (y > s.length()) y = s.length();
  return s.substring(x, y);
}
static String substring(String s, IntRange r) {
  return r == null ? null : substring(s, r.start, r.end);
}
// convenience method for quickly dropping a prefix
static String substring(String s, CharSequence l) {
  return substring(s, l(l));
}
static  Set keys(Map map) {
  return map == null ? new HashSet() : map.keySet();
}
// convenience shortcut for keys_gen
static Set keys(Object map) {
  return keys((Map) map);
}
  static  Set keys(MultiMap mm) {
    return mm.keySet();
  }
  static  Set keys(MultiSetMap mm) {
    return mm.keySet();
  }
static int[] toIntArray(Collection l) {
  int[] a = new int[l(l)];
  int i = 0;
  if (a.length != 0) for (int x : l)
    a[i++] = x;
  return a;
}
// get purpose 1: access a list/array/map (safer version of x.get(y))
static  A get(List l, int idx) {
  return l != null && idx >= 0 && idx < l(l) ? l.get(idx) : null;
}
// seems to conflict with other signatures
/*static  B get(Map map, A key) {
  ret map != null ? map.get(key) : null;
}*/
static  A get(A[] l, int idx) {
  return idx >= 0 && idx < l(l) ? l[idx] : null;
}
// default to false
static boolean get(boolean[] l, int idx) {
  return idx >= 0 && idx < l(l) ? l[idx] : false;
}
// get purpose 2: access a field by reflection or a map
static Object get(Object o, String field) {
  try {
    if (o == null) return null;
    if (o instanceof Class) return get((Class) o, field);
    
    if (o instanceof Map)
      return ((Map) o).get(field);
      
    Field f = getOpt_findField(o.getClass(), field);
    if (f != null) {
      makeAccessible(f);
      return f.get(o);
    }
      
    
  } catch (Exception e) {
    throw asRuntimeException(e);
  }
  throw new RuntimeException("Field '" + field + "' not found in " + o.getClass().getName());
}
static Object get_raw(String field, Object o) {
  return get_raw(o, field);
}
static Object get_raw(Object o, String field) { try {
  if (o == null) return null;
  Field f = get_findField(o.getClass(), field);
  makeAccessible(f);
  return f.get(o);
} catch (Exception __e) { throw rethrow(__e); } }
static Object get(Class c, String field) {
  try {
    Field f = get_findStaticField(c, field);
    makeAccessible(f);
    return f.get(null);
  } catch (Exception e) {
    throw new RuntimeException(e);
  }
}
static Field get_findStaticField(Class> c, String field) {
  Class _c = c;
  do {
    for (Field f : _c.getDeclaredFields())
      if (f.getName().equals(field) && (f.getModifiers() & java.lang.reflect.Modifier.STATIC) != 0)
        return f;
    _c = _c.getSuperclass();
  } while (_c != null);
  throw new RuntimeException("Static field '" + field + "' not found in " + c.getName());
}
static Field get_findField(Class> c, String field) {
  Class _c = c;
  do {
    for (Field f : _c.getDeclaredFields())
      if (f.getName().equals(field))
        return f;
    _c = _c.getSuperclass();
  } while (_c != null);
  throw new RuntimeException("Field '" + field + "' not found in " + c.getName());
}
static Object get(String field, Object o) {
  return get(o, field);
}
static boolean boolPar(ThreadLocal tl) {
  return boolOptParam(tl);
}
// defaults to false
static boolean boolPar(Object[] __, String name) {
  return boolOptParam(__, name);
}
static boolean boolPar(String name, Object[] __) {
  return boolOptParam(__, name);
}
static boolean boolPar(String name, Map __) {
  return boolOptParam(name, __);
}
static boolean boolPar(String name, Object[] params, boolean defaultValue) {
  return optParam(params, name, defaultValue);
}
static boolean empty(Collection c) { return c == null || c.isEmpty(); }
static boolean empty(CharSequence s) { return s == null || s.length() == 0; }
static boolean empty(Map map) { return map == null || map.isEmpty(); }
static boolean empty(Object[] o) { return o == null || o.length == 0; }
static boolean empty(Object o) {
  if (o instanceof Collection) return empty((Collection) o);
  if (o instanceof String) return empty((String) o);
  if (o instanceof Map) return empty((Map) o);
  if (o instanceof Object[]) return empty((Object[]) o);
  if (o instanceof byte[]) return empty((byte[]) o);
  if (o == null) return true;
  throw fail("unknown type for 'empty': " + getType(o));
}
static boolean empty(Iterator i) { return i == null || !i.hasNext(); }
static boolean empty(double[] a) { return a == null || a.length == 0; }
static boolean empty(float[] a) { return a == null || a.length == 0; }
static boolean empty(int[] a) { return a == null || a.length == 0; }
static boolean empty(long[] a) { return a == null || a.length == 0; }
static boolean empty(byte[] a) { return a == null || a.length == 0; }
static boolean empty(short[] a) { return a == null || a.length == 0; }
static boolean empty(MultiMap mm) { return mm == null || mm.isEmpty(); }
static boolean empty(File f) { return getFileSize(f) == 0; }
static boolean empty(IntRange r) { return r == null || r.empty(); }
static int l(Object[] a) { return a == null ? 0 : a.length; }
static int l(boolean[] a) { return a == null ? 0 : a.length; }
static int l(byte[] a) { return a == null ? 0 : a.length; }
static int l(short[] a) { return a == null ? 0 : a.length; }
static int l(long[] a) { return a == null ? 0 : a.length; }
static int l(int[] a) { return a == null ? 0 : a.length; }
static int l(float[] a) { return a == null ? 0 : a.length; }
static int l(double[] a) { return a == null ? 0 : a.length; }
static int l(char[] a) { return a == null ? 0 : a.length; }
static int l(Collection c) { return c == null ? 0 : c.size(); }
static int l(Iterator i) { return iteratorCount_int_close(i); } // consumes the iterator && closes it if possible
static int l(Map m) { return m == null ? 0 : m.size(); }
static int l(CharSequence s) { return s == null ? 0 : s.length(); }
static long l(File f) { return f == null ? 0 : f.length(); }
static int l(Object o) {
  return o == null ? 0
    : o instanceof String ? l((String) o)
    : o instanceof Map ? l((Map) o)
    : o instanceof Collection ? l((Collection) o)
    : o instanceof Object[] ? l((Object[]) o)
    : o instanceof boolean[] ? l((boolean[]) o)
    : o instanceof byte[] ? l((byte[]) o)
    : o instanceof char[] ? l((char[]) o)
    : o instanceof short[] ? l((short[]) o)
    : o instanceof int[] ? l((int[]) o)
    : o instanceof float[] ? l((float[]) o)
    : o instanceof double[] ? l((double[]) o)
    : o instanceof long[] ? l((long[]) o)
    : (Integer) call(o, "size");
}
  static int l(IntRange r) { return r == null ? 0 : r.length(); }
static Object first(Object list) {
  return first((Iterable) list);
}
static  A first(List list) {
  return empty(list) ? null : list.get(0);
}
static  A first(A[] bla) {
  return bla == null || bla.length == 0 ? null : bla[0];
}
static  A first(Iterator i) {
  return i == null || !i.hasNext() ? null : i.next();
}
static  A first(Iterable i) {
  if (i == null) return null;
  Iterator it = i.iterator();
  return it.hasNext() ? it.next() : null;
}
static Character first(String s) { return empty(s) ? null : s.charAt(0); }
static  A first(Pair p) {
  return p == null ? null : p.a;
}
static Byte first(byte[] l) { 
  return empty(l) ? null : l[0];
}
static  A last(List l) {
  return empty(l) ? null : l.get(l.size()-1);
}
static char last(String s) {
  return empty(s) ? '#' : s.charAt(l(s)-1);
}
static int last(int[] a) {
  return l(a) != 0 ? a[l(a)-1] : 0;
}
static double last(double[] a) {
  return l(a) != 0 ? a[l(a)-1] : 0;
}
static  A last(A[] a) {
  return l(a) != 0 ? a[l(a)-1] : null;
}
static  A last(Iterator it) {
  A a = null;
  while  (it.hasNext()) { ping(); a = it.next(); }
  return a;
}
static  A last(Collection l) {
  if (l == null) return null;
  if (l instanceof List) return (A) last(((List) l));
  if (l instanceof SortedSet) return (A) last(((SortedSet) l));
  Iterator it = iterator(l);
  A a = null;
  while  (it.hasNext()) { ping(); a = it.next(); }
  return a;
}
static  A last(SortedSet l) {
  return l == null ? null : l.last();
}
static List map(Iterable l, Object f) { return map(f, l); }
static List map(Object f, Iterable l) {
  List x = emptyList(l);
  if (l != null) for (Object o : l)
    x.add(callF(f, o));
  return x;
}
  static  List map(Iterable l, F1 f) { return map(f, l); }
  static  List map(F1 f, Iterable l) {
    List x = emptyList(l);
    if (l != null) for (A o : l)
      x.add(callF(f, o));
    return x;
  }
static  List map(IF1 f, Iterable l) { return map(l, f); }
static  List map(Iterable l, IF1 f) {
  List x = emptyList(l);
  if (l != null) for (A o : l)
    x.add(f.get(o));
  return x;
}
  
static  List map(IF1 f, A[] l) { return map(l, f); }
static  List map(A[] l, IF1 f) {
  List x = emptyList(l);
  if (l != null) for (A o : l)
    x.add(f.get(o));
  return x;
}
  
static List map(Object f, Object[] l) { return map(f, asList(l)); }
static List map(Object[] l, Object f) { return map(f, l); }
static List map(Object f, Map map) {
  return map(map, f);
}
// map: func(key, value) -> list element
static List map(Map map, Object f) {
  List x = new ArrayList();
  if (map != null) for (Object _e : map.entrySet()) {
    Map.Entry e = (Map.Entry) _e;
    x.add(callF(f, e.getKey(), e.getValue()));
  }
  return x;
}
static  List map(Map map, IF2 f) {
  return map(map, (Object) f);
}
static ArrayList emptyList() {
  return new ArrayList();
  //ret Collections.emptyList();
}
static ArrayList emptyList(int capacity) {
  return new ArrayList(max(0, capacity));
}
// Try to match capacity
static ArrayList emptyList(Iterable l) {
  return l instanceof Collection ? emptyList(((Collection) l).size()) : emptyList();
}
static ArrayList emptyList(Object[] l) {
  return emptyList(l(l));
}
// get correct type at once
static  ArrayList emptyList(Class c) {
  return new ArrayList();
}
static volatile StringBuffer local_log = new StringBuffer(); // not redirected
static volatile Appendable print_log = local_log; // might be redirected, e.g. to main bot
// in bytes - will cut to half that
static volatile int print_log_max = 1024*1024;
static volatile int local_log_max = 100*1024;
static boolean print_silent = false; // total mute if set
static Object print_byThread_lock = new Object();
static volatile ThreadLocal