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.*;
public class main {
public static void main(final String[] args) throws Exception {
  flexMatchIC2_debug = true;
  Matches m = getFlexMatchIC2("*?", "yes?");
  assertEquals("yes", m.unq(0));
}
static Matches getFlexMatchIC2(String pat, String s) {
  Matches m = new Matches();
  return flexMatchIC2(pat, s, m) ? m : null;
}
static  A assertEquals(Object x, A y) {
  return assertEquals(null, x, y);
}
static  A assertEquals(String msg, Object x, A y) {
  if (!(x == null ? y == null : x.equals(y)))
    throw fail((msg != null ? msg + ": " : "") + y + " != " + x);
  return y;
}
static boolean flexMatchIC2_debug;
static boolean flexMatchIC2(String pat, String s) {
  return flexMatchIC2(pat, s, null);
}
static boolean flexMatchIC2(String pat, String s, Matches m) {
  return flexMatchIC2(javaTok(pat), javaTok(s), m);
}
static boolean flexMatchIC2(List tokpat, List tokfull, Matches m) {
  tokpat = codeTokens(joinBrackets(tokpat));
  for (int i = 0; i < l(tokpat); i++)
    if (eq(tokpat.get(i), "*"))
      tokpat.add(i++, "!*"); // insert single-token wildcard in front to avoid empty matches
  tokfull = joinBrackets(tokfull);
  List tok = codeTokens(tokfull);
  BitSet bla = new BitSet();
  BitSet bla2 = new BitSet();
  if (!flexMatchIC2_impl(tokpat, 0, tok, 0, bla, bla2)) return false;
  if (m != null) {
    List l = new ArrayList();
    for (int i = 1; i < l(tokfull); i += 2) {
      if (bla.get(i/2)) {
        int j = i;
        while (j < l(tokfull) && bla.get(j/2)) j += 2;
        l.add(join(subList(tokfull, i, j-1)));
        i = j-2;
      } else if (bla2.get(i/2))
        l.add(tokfull.get(i));
    }
    m.m = toStringArray(l);
  }
  return true;
}
static boolean flexMatchIC2_impl(List pat, int ipat, List tok, int itok, BitSet bla, BitSet bla2) {
  if (flexMatchIC2_debug)
    print("flexMatchIC2 pat=" + structure(subList(pat, ipat)) + " tok=" + structure(subList(tok, itok)) + " " + structure(bla));
  if (ipat >= l(pat))
    return itok >= l(tok);
  String t = pat.get(ipat);
  
  if (eq(t, "*")) { // the flex wildcard (0 or more tokens)
    if (flexMatchIC2_debug) print("Trying zero tokens");
    if (flexMatchIC2_impl(pat, ipat+1, tok, itok, bla, bla2)) {
      if (flexMatchIC2_debug) print("Success!");
      return true;
    }
    
    bla.set(itok);
    if (itok < l(tok)) {
      if (flexMatchIC2_debug) print("Trying one or more tokens");
      if (flexMatchIC2_impl(pat, ipat, tok, itok+1, bla, bla2)) {
        if (flexMatchIC2_debug) print("Success!");
        return true; // success, leave mark
      }
    }
    
    if (flexMatchIC2_debug) print("Failed * matching");
    bla.clear(itok); // fail, undo marking
    return false;
  }
  if (itok >= l(tok)) {
    if (flexMatchIC2_debug)
      print("too much pattern");
    return false;
  }
  if (eq(t, "!*")) { // the single-token wildcard
    bla.set(itok);
    if (flexMatchIC2_impl(pat, ipat+1, tok, itok+1, bla, bla2))
      return true; // success, leave mark
    bla.clear(itok); // fail, undo marking
    return false;
  }
  String realt = tok.get(itok);
  if (t.startsWith("(") && t.endsWith(")")) {
    // quick pre-check
    if (flexMatchIC2_debug)
      print("flexMatchIC2 precheck " + t + " " + realt);
    if (!containsIgnoreCase(t, realt)) return false;
    // real check
    List list = splitAt(dropFirstAndLast(t), "|");
    if (flexMatchIC2_debug)
      print("flexMatchIC2 real check " + struct(list));
    if (!containsIgnoreCase(list, realt)) return false;
    bla2.set(itok);
  } else if (neqic(realt, t)) {
    if (flexMatchIC2_debug)
      print("mismatch");
    return false;
  }
  
  // it is a token match. consume and proceed
  if (flexMatchIC2_impl(pat, ipat+1, tok, itok+1, bla, bla2))
    return true;
  else {
    bla2.clear(itok);
    return false;
  }
}
  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(unnull(msg));
  }
   
  static RuntimeException fail(String msg, Throwable innerException) {
    throw new RuntimeException(msg, innerException);
  }
  
  // disabled for now to shorten some programs 
  /*static RuntimeException fail(S msg, O... args) {
    throw new RuntimeException(format(msg, args));
  }*/
static String struct(Object o) {
  return structure(o);
}
static  List subList(List l, int startIndex) {
  return subList(l, startIndex, l(l));
}
static  List subList(List l, int startIndex, int endIndex) {
  startIndex = max(0, min(l(l), startIndex));
  endIndex = max(0, min(l(l), endIndex));
  if (startIndex > endIndex) return litlist();
  return l.subList(startIndex, endIndex);
}
// TODO: returns empty first, but not empty last
static List splitAt(String s, String splitter) {
  List parts = new ArrayList();
  int i = 0;
  if (s != null)
    while (i < l(s)) {
      int j = indexOf(s, splitter, i);
      if (j < 0) j = l(s);
      parts.add(substring(s, i, j));
      i = j+l(splitter);
    }
  return parts;
}
static List codeTokens(List tok) {
  return codeTokensOnly(tok);
}
// replacement for class JavaTok
// maybe incomplete, might want to add floating point numbers
// todo also: extended multi-line strings
static int javaTok_n, javaTok_elements;
static boolean javaTok_opt;
static List javaTok(String s) {
  return javaTok(s, null);
}
static List javaTok(String s, List existing) {
  ++javaTok_n;
  int nExisting = javaTok_opt && existing != null ? existing.size() : 0;
  ArrayList tok = existing != null ? new ArrayList(nExisting) : new ArrayList();
  int l = s.length();
  
  int i = 0, n = 0;
  while (i < l) {
    int j = i;
    char c, d;
    
    // scan for whitespace
    while (j < l) {
      c = s.charAt(j);
      d = j+1 >= l ? '\0' : s.charAt(j+1);
      if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
        ++j;
      else if (c == '/' && d == '*') {
        do ++j; while (j < l && !s.substring(j, Math.min(j+2, l)).equals("*/"));
        j = Math.min(j+2, l);
      } else if (c == '/' && d == '/') {
        do ++j; while (j < l && "\r\n".indexOf(s.charAt(j)) < 0);
      } else
        break;
    }
    
    if (n < nExisting && javaTok_isCopyable(existing.get(n), s, i, j))
      tok.add(existing.get(n));
    else
      tok.add(quickSubstring(s, i, j));
    ++n;
    i = j;
    if (i >= l) break;
    c = s.charAt(i);
    d = i+1 >= l ? '\0' : s.charAt(i+1);
    // scan for non-whitespace
    if (c == '\'' || c == '"') {
      char opener = c;
      ++j;
      while (j < l) {
        if (s.charAt(j) == opener /*|| s.charAt(j) == '\n'*/) { // allow multi-line strings
          ++j;
          break;
        } else if (s.charAt(j) == '\\' && j+1 < l)
          j += 2;
        else
          ++j;
      }
    } else if (Character.isJavaIdentifierStart(c))
      do ++j; while (j < l && (Character.isJavaIdentifierPart(s.charAt(j)) || "'".indexOf(s.charAt(j)) >= 0)); // for stuff like "don't"
    else if (Character.isDigit(c)) {
      do ++j; while (j < l && Character.isDigit(s.charAt(j)));
      if (j < l && s.charAt(j) == 'L') ++j; // Long constants like 1L
    } else if (c == '[' && d == '[') {
      do ++j; while (j+1 < l && !s.substring(j, j+2).equals("]]"));
      j = Math.min(j+2, l);
    } else if (c == '[' && d == '=' && i+2 < l && s.charAt(i+2) == '[') {
      do ++j; while (j+2 < l && !s.substring(j, j+3).equals("]=]"));
      j = Math.min(j+3, l);
    } else
      ++j;
      
    if (n < nExisting && javaTok_isCopyable(existing.get(n), s, i, j))
      tok.add(existing.get(n));
    else
      tok.add(quickSubstring(s, i, j));
    ++n;
    i = j;
  }
  
  if ((tok.size() % 2) == 0) tok.add("");
  javaTok_elements += tok.size();
  return tok;
}
static List javaTok(List tok) {
  return javaTok(join(tok), tok);
}
static boolean javaTok_isCopyable(String t, String s, int i, int j) {
  return t.length() == j-i
    && s.regionMatches(i, t, 0, j-i); // << could be left out, but that's brave
}
static String unnull(String s) {
  return s == null ? "" : s;
}
static  List unnull(List l) {
  return l == null ? emptyList() : l;
}
static  Iterable unnull(Iterable i) {
  return i == null ? emptyList() : i;
}
static Object[] unnull(Object[] a) {
  return a == null ? new Object[0] : a;
}
static BitSet unnull(BitSet b) {
  return b == null ? new BitSet() : b;
}
static boolean neqic(String a, String b) {
  return !eqic(a, b);
}
static List joinBrackets(List tok) {
  List t = new ArrayList();
  Map map = getBracketMap(tok);
  for (int i = 0; i < l(tok); i++) {
    Integer dest = map.get(i);
    if (dest != null) {
      t.add(join(subList(tok, i, dest+1)));
      i = dest;
    } else
      t.add(tok.get(i));
  }
  return t;
}
static boolean containsIgnoreCase(List l, String s) {
  for (String x : l)
    if (eqic(x, s))
      return true;
  return false;
}
static boolean containsIgnoreCase(String[] l, String s) {
  for (String x : l)
    if (eqic(x, s))
      return true;
  return false;
}
static boolean containsIgnoreCase(String s, char c) {
  return indexOfIgnoreCase(s, String.valueOf(c)) >= 0;
}
static boolean containsIgnoreCase(String a, String b) {
  return indexOfIgnoreCase(a, b) >= 0;
}
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(int[] a) { return a == null ? 0 : a.length; }
static int l(float[] 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(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 instanceof String ? l((String) o)
    : l((Collection) o); // incomplete
}
static boolean eq(Object a, Object b) {
  if (a == null) return b == null;
  if (a.equals(b)) return true;
  if (a instanceof BigInteger) {
    if (b instanceof Integer) return a.equals(BigInteger.valueOf((Integer) b));
    if (b instanceof Long) return a.equals(BigInteger.valueOf((Long) b));
  }
  return false;
}
static String[] toStringArray(Collection c) {
  String[] a = new String[l(c)];
  Iterator it = c.iterator();
  for (int i = 0; i < l(a); i++)
    a[i] = it.next();
  return a;
}
static String[] toStringArray(Object o) {
  if (o instanceof String[])
    return (String[]) o;
  else if (o instanceof Collection)
    return toStringArray((Collection) o);
  else
    throw fail("Not a collection or array: " + getClassName(o));
}
static boolean structure_showTiming, structure_checkTokenCount;
static String structure(Object o) {
  structure_Data d = new structure_Data();
  StringWriter sw = new StringWriter();
  d.out = new PrintWriter(sw);
  structure_go(o, d);
  String s = str(sw);
  if (structure_checkTokenCount) {
    print("token count=" + d.n);
    assertEquals("token count", l(javaTokC(s)), d.n);
  }
  return s;
}
static void structure_go(Object o, structure_Data d) {
  structure_1(o, d);
  while (nempty(d.stack))
    popLast(d.stack).run();
}
static void structureToPrintWriter(Object o, PrintWriter out) {
  structure_Data d = new structure_Data();
  d.out = out;
  structure_go(o, d);
}
// leave to false, unless unstructure() breaks
static boolean structure_allowShortening = false;
static int structure_shareStringsLongerThan = 20;
static class structure_Data {
  PrintWriter out;
  int stringSizeLimit;
  IdentityHashMap