#include <bits/stdc++.h>
#define clr(x) memset((x), 0, sizeof(x))
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define mp make_pair
#define For(i, st, en) for(int i=(st); i<=(int)(en); i++)
#define Ford(i, st, en) for(int i=(st); i>=(int)(en); i--)
#define forn(i, n) for(int i=0; i<(int)(n); i++)
#define ford(i, n) for(int i=(n)-1; i>=0; i--)
#define fori(it, x) for (__typeof((x).begin()) it = (x).begin(); it != (x).end(); it++)
#define in(x) int (x); input((x));
#define x first
#define y second
#define less(a,b) ((a) < (b) - EPS)
#define more(a,b) ((a) > (b) + EPS)
#define eq(a,b) (fabs((a) - (b)) < EPS)
#define remax(a, b) ((a) = (b) > (a) ? (b) : (a))
#define remin(a, b) ((a) = (b) < (a) ? (b) : (a))
using namespace std;
template <typename T>
T gcd(T a, T b) {
while (b > 0) {
a %= b;
swap(a, b);
}
return a;
}
typedef long double ld; typedef unsigned int uint; template <class _T> inline _T sqr(const _T& x) {return x * x;} template <class _T> inline string tostr(const _T& a) {ostringstream os(""); os << a; return os.str();} const ld PI = 3.1415926535897932384626433832795L; const double EPS = 1e-9; char TEMPORARY_CHAR;
typedef long long ll; typedef unsigned long long ull; typedef set < int > SI; typedef vector < int > VI; typedef vector < vector < int > > VVI; typedef map < string, int > MSI; typedef pair < int, int > PII; const int INF = 1e9; inline void input(int &a) {a = 0; while (((TEMPORARY_CHAR = getchar()) > '9' || TEMPORARY_CHAR < '0') && (TEMPORARY_CHAR != '-')){} char neg = 0; if (TEMPORARY_CHAR == '-') {neg = 1; TEMPORARY_CHAR = getchar();} while (TEMPORARY_CHAR <= '9' && TEMPORARY_CHAR >= '0') {a = 10 * a + TEMPORARY_CHAR - '0'; TEMPORARY_CHAR = getchar();} if (neg) a = -a;} inline void out(long long a) {if (!a) putchar('0'); if (a < 0) {putchar('-'); a = -a;} char s[20]; int i; for(i = 0; a; ++i) {s[i] = '0' + a % 10; a /= 10;} ford(j, i) putchar(s[j]);} inline int nxt() {in(ret); return ret;}
const int MAXN = 1000000;
const int LOG = 1000;
namespace suf_array {
static const int MAXLEN = MAXN * 2;
static const int LOG = 20;
char s[MAXLEN + 1];
int n;
int sa[MAXLEN];
int lcp[MAXLEN];
int logTable[MAXLEN];
int rank[MAXLEN];
int rmq[LOG + 1][MAXLEN];
int order[MAXLEN];
int r[MAXLEN];
int cnt[MAXLEN];
int st[MAXLEN];
bool cmp(int i, int j) {
return s[i] < s[j];
}
void process()
{
for (int i = 0; i < n; i++)
order[i] = n - 1 - i;
stable_sort(order, order + n, cmp);
for (int i = 0; i < n; i++) {
sa[i] = order[i];
rank[i] = s[i];
}
for (int len = 1; len < n; len <<= 1) {
memcpy(r, rank, n * sizeof(int));
for (int i = 0; i < n; i++) {
rank[sa[i]] = (i > 0 && r[sa[i - 1]] == r[sa[i]] &&
sa[i - 1] + len < n && r[sa[i - 1] + len / 2] == r[sa[i] + len / 2])
? rank[sa[i - 1]]
: i;
}
for (int i = 0; i < n; i++)
cnt[i] = i;
memcpy(st, sa, sizeof(int) * n);
for (int i = 0; i < n; i++) {
int s1 = st[i] - len;
if (s1 >= 0)
sa[cnt[rank[s1]]++] = s1;
}
}
}
void calc_lcp() {
for (int i = 0; i < n; i++)
rank[sa[i]] = i;
for (int i = 0, h = 0; i < n; i++) {
if (rank[i] < n - 1) {
int j = sa[rank[i] + 1];
while(max(i, j) + h < n && s[i + h] == s[j + h])
++h;
lcp[rank[i] + 1] = h;
if (h > 0)
--h;
}
}
logTable[0] = 0;
logTable[1] = 0;
for (int i = 2; i < n; i++)
logTable[i] = logTable[i >> 1] + 1;
for (int i = 0; i < n; ++i)
rmq[0][i] = lcp[i];
for (int k = 1; (1 << k) < n; ++k) {
for (int i = 0; i + (1 << k) <= n; i++) {
int x = rmq[k - 1][i];
int y = rmq[k - 1][i + (1 << k - 1)];
rmq[k][i] = min(x, y);
}
}
}
int get_lcp(int l, int r) {
l = rank[l];
r = rank[r];
if (l > r) {
swap(l, r);
}
if (l == r) {
return n - sa[l];
}
++l;
int k = logTable[r - l];
int x = rmq[k][l];
int y = rmq[k][r - (1 << k) + 1];
return min(x, y);
}
};
namespace hld {
vector <int> g[MAXN];
int sz[MAXN];
int p[MAXN];
int pos_up[MAXN];
int pos_down[MAXN];
int r[MAXN];
int root[MAXN];
int rt[MAXN];
int tin[MAXN];
int tout[MAXN];
int timer = 0;
int pos[MAXN];
vector <int> c[MAXN];
int pathCount = 0;
void dfs(int v, int par) {
p[v] = par;
sz[v] = 1;
tin[v] = timer++;
for (int i = 0; i < (int)g[v].size(); ++i) {
int to = g[v][i];
if (to == par) {
continue;
}
dfs(to, v);
sz[v] += sz[to];
}
tout[v] = timer++;
}
void decomp(int v, int par, int k) {
pos[v] = c[k].size();
c[k].push_back(v);
root[v] = rt[k];
r[v] = k;
int x = 0, y = -1;
for (int i = 0; i < (int)g[v].size(); ++i) {
int to = g[v][i];
if (to == par)
continue;
if (sz[to] > x) {
x = sz[to];
y = to;
}
}
if (y != -1) decomp(y, v, k);
for (int i = 0; i < (int)g[v].size(); ++i) {
int to = g[v][i];
if (to != par && to != y) {
rt[pathCount] = to;
decomp(to, v, pathCount++);
}
}
}
void initSA(char * s, char * data) {
int len = 0;
for (int i = 0; i < pathCount; ++i) {
for (int j = 0; j < (int)c[i].size(); ++j) {
int v = c[i][j];
s[pos_down[v] = len++] = data[v];
}
for (int j = (int)c[i].size() - 1; j >= 0; --j) {
int v = c[i][j];
s[pos_up[v] = len++] = data[v];
}
}
}
inline bool upper(int a, int b) {
return tin[a] <= tin[b] && tout[a] >= tout[b];
}
pair <int, int> up[LOG];
pair <int, int> down[LOG];
int getHeavySegments(int a, int b, pair <int, int> * res) {
int sup = 0;
int sdown = 0;
while (!upper(root[a], b)) {
up[sup++] = make_pair(pos_up[a], pos_up[root[a]]);
a = p[root[a]];
}
while (!upper(root[b], a)) {
down[sdown++] = make_pair(pos_down[root[b]], pos_down[b]);
b = p[root[b]];
}
assert(r[a] == r[b]);
if (upper(a, b)) {
down[sdown++] = make_pair(pos_down[a], pos_down[b]);
} else {
up[sup++] = make_pair(pos_up[a], pos_up[b]);
}
for (int i = 0; i < sup; ++i) {
*res++ = up[i];
}
for (int i = sdown - 1; i >= 0; --i) {
*res++ = down[i];
}
return sup + sdown;
}
}
int main() {
#ifdef LOCAL
freopen("input.txt", "r", stdin);
#else
#endif
ios_base::sync_with_stdio(false);
int n;
scanf("%d", &n);
char data[n + 1];
scanf("%s", data);
for (int i = 0; i + 1 < n; ++i) {
int a, b;
scanf("%d%d", &a, &b);
--a, --b;
hld::g[a].push_back(b);
hld::g[b].push_back(a);
}
hld::dfs(0, -1);
hld::decomp(0, -1, hld::pathCount++);
hld::initSA(suf_array::s, data);
suf_array::n = 2 * n;
suf_array::process();
suf_array::calc_lcp();
int m;
scanf("%d", &m);
pair <int, int> segsL[LOG];
pair <int, int> segsR[LOG];
while (m--) {
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
--a, --b, --c, --d;
int lsize = hld::getHeavySegments(a, b, segsL);
int rsize = hld::getHeavySegments(c, d, segsR);
int i = 0, j = 0;
int len = 0;
while (i < lsize && j < rsize) {
int lcp = suf_array::get_lcp(segsL[i].first, segsR[j].first);
lcp = min(lcp, segsL[i].second - segsL[i].first + 1);
lcp = min(lcp, segsR[j].second - segsR[j].first + 1);
len += lcp;
segsL[i].first += lcp;
segsR[j].first += lcp;
bool ok = false;
if (segsL[i].first > segsL[i].second) {
++i;
ok = true;
}
if (segsR[j].first > segsR[j].second) {
++j;
ok = true;
}
if (!ok) {
break;
}
}
printf("%d\n", len);
}
#ifdef LOCAL
cerr << "Time elapsed: " << (double)clock() / CLOCKS_PER_SEC * 1000 << " ms.\n";
#endif // LOCAL
return 0;
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CgojZGVmaW5lIGNscih4KSBtZW1zZXQoKHgpLCAwLCBzaXplb2YoeCkpCiNkZWZpbmUgYWxsKHgpICh4KS5iZWdpbigpLCAoeCkuZW5kKCkKI2RlZmluZSBwYiBwdXNoX2JhY2sKI2RlZmluZSBtcCBtYWtlX3BhaXIKI2RlZmluZSBGb3IoaSwgc3QsIGVuKSBmb3IoaW50IGk9KHN0KTsgaTw9KGludCkoZW4pOyBpKyspCiNkZWZpbmUgRm9yZChpLCBzdCwgZW4pIGZvcihpbnQgaT0oc3QpOyBpPj0oaW50KShlbik7IGktLSkKI2RlZmluZSBmb3JuKGksIG4pIGZvcihpbnQgaT0wOyBpPChpbnQpKG4pOyBpKyspCiNkZWZpbmUgZm9yZChpLCBuKSBmb3IoaW50IGk9KG4pLTE7IGk+PTA7IGktLSkKI2RlZmluZSBmb3JpKGl0LCB4KSBmb3IgKF9fdHlwZW9mKCh4KS5iZWdpbigpKSBpdCA9ICh4KS5iZWdpbigpOyBpdCAhPSAoeCkuZW5kKCk7IGl0KyspCiNkZWZpbmUgaW4oeCkgaW50ICh4KTsgaW5wdXQoKHgpKTsKI2RlZmluZSB4IGZpcnN0CiNkZWZpbmUgeSBzZWNvbmQKI2RlZmluZSBsZXNzKGEsYikgKChhKSA8IChiKSAtIEVQUykKI2RlZmluZSBtb3JlKGEsYikgKChhKSA+IChiKSArIEVQUykKI2RlZmluZSBlcShhLGIpIChmYWJzKChhKSAtIChiKSkgPCBFUFMpCiNkZWZpbmUgcmVtYXgoYSwgYikgKChhKSA9IChiKSA+IChhKSA/IChiKSA6IChhKSkKI2RlZmluZSByZW1pbihhLCBiKSAoKGEpID0gKGIpIDwgKGEpID8gKGIpIDogKGEpKQoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgpUIGdjZChUIGEsIFQgYikgewogICAgd2hpbGUgKGIgPiAwKSB7CiAgICAgICAgYSAlPSBiOwogICAgICAgIHN3YXAoYSwgYik7CiAgICB9CiAgICByZXR1cm4gYTsKfQoKdHlwZWRlZiBsb25nIGRvdWJsZSBsZDsgdHlwZWRlZiB1bnNpZ25lZCBpbnQgdWludDsgdGVtcGxhdGUgPGNsYXNzIF9UPiBpbmxpbmUgX1Qgc3FyKGNvbnN0IF9UJiB4KSB7cmV0dXJuIHggKiB4O30gdGVtcGxhdGUgPGNsYXNzIF9UPiBpbmxpbmUgc3RyaW5nIHRvc3RyKGNvbnN0IF9UJiBhKSB7b3N0cmluZ3N0cmVhbSBvcygiIik7IG9zIDw8IGE7IHJldHVybiBvcy5zdHIoKTt9IGNvbnN0IGxkIFBJID0gMy4xNDE1OTI2NTM1ODk3OTMyMzg0NjI2NDMzODMyNzk1TDsgY29uc3QgZG91YmxlIEVQUyA9IDFlLTk7IGNoYXIgVEVNUE9SQVJZX0NIQVI7Cgp0eXBlZGVmIGxvbmcgbG9uZyBsbDsgdHlwZWRlZiB1bnNpZ25lZCBsb25nIGxvbmcgdWxsOyB0eXBlZGVmIHNldCA8IGludCA+IFNJOyB0eXBlZGVmIHZlY3RvciA8IGludCA+IFZJOyB0eXBlZGVmIHZlY3RvciA8IHZlY3RvciA8IGludCA+ID4gVlZJOyB0eXBlZGVmIG1hcCA8IHN0cmluZywgaW50ID4gTVNJOyB0eXBlZGVmIHBhaXIgPCBpbnQsIGludCA+IFBJSTsgY29uc3QgaW50IElORiA9IDFlOTsgaW5saW5lIHZvaWQgaW5wdXQoaW50ICZhKSB7YSA9IDA7IHdoaWxlICgoKFRFTVBPUkFSWV9DSEFSID0gZ2V0Y2hhcigpKSA+ICc5JyB8fCBURU1QT1JBUllfQ0hBUiA8ICcwJykgJiYgKFRFTVBPUkFSWV9DSEFSICE9ICctJykpe30gY2hhciBuZWcgPSAwOyBpZiAoVEVNUE9SQVJZX0NIQVIgPT0gJy0nKSB7bmVnID0gMTsgVEVNUE9SQVJZX0NIQVIgPSBnZXRjaGFyKCk7fSB3aGlsZSAoVEVNUE9SQVJZX0NIQVIgPD0gJzknICYmIFRFTVBPUkFSWV9DSEFSID49ICcwJykge2EgPSAxMCAqIGEgKyBURU1QT1JBUllfQ0hBUiAtICcwJzsgVEVNUE9SQVJZX0NIQVIgPSBnZXRjaGFyKCk7fSBpZiAobmVnKSBhID0gLWE7fSBpbmxpbmUgdm9pZCBvdXQobG9uZyBsb25nIGEpIHtpZiAoIWEpIHB1dGNoYXIoJzAnKTsgaWYgKGEgPCAwKSB7cHV0Y2hhcignLScpOyBhID0gLWE7fSBjaGFyIHNbMjBdOyBpbnQgaTsgZm9yKGkgPSAwOyBhOyArK2kpIHtzW2ldID0gJzAnICsgYSAlIDEwOyBhIC89IDEwO30gZm9yZChqLCBpKSBwdXRjaGFyKHNbal0pO30gaW5saW5lIGludCBueHQoKSB7aW4ocmV0KTsgcmV0dXJuIHJldDt9Cgpjb25zdCBpbnQgTUFYTiA9IDEwMDAwMDA7CmNvbnN0IGludCBMT0cgPSAxMDAwOwoKbmFtZXNwYWNlIHN1Zl9hcnJheSB7CiAgICBzdGF0aWMgY29uc3QgaW50IE1BWExFTiA9IE1BWE4gKiAyOwogICAgc3RhdGljIGNvbnN0IGludCBMT0cgPSAyMDsKICAgIGNoYXIgc1tNQVhMRU4gKyAxXTsKICAgIGludCBuOwogICAgaW50IHNhW01BWExFTl07CiAgICBpbnQgbGNwW01BWExFTl07CiAgICBpbnQgbG9nVGFibGVbTUFYTEVOXTsKICAgIGludCByYW5rW01BWExFTl07CiAgICBpbnQgcm1xW0xPRyArIDFdW01BWExFTl07CiAgICBpbnQgb3JkZXJbTUFYTEVOXTsKICAgIGludCByW01BWExFTl07CiAgICBpbnQgY250W01BWExFTl07CiAgICBpbnQgc3RbTUFYTEVOXTsKCiAgICBib29sIGNtcChpbnQgaSwgaW50IGopICB7CiAgICAgICAgcmV0dXJuIHNbaV0gPCBzW2pdOwogICAgfQoKICAgIHZvaWQgcHJvY2VzcygpCiAgICB7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspCiAgICAgICAgICAgIG9yZGVyW2ldID0gbiAtIDEgLSBpOwoKICAgICAgICBzdGFibGVfc29ydChvcmRlciwgb3JkZXIgKyBuLCBjbXApOwoKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IG47IGkrKykgewogICAgICAgICAgICBzYVtpXSA9IG9yZGVyW2ldOwogICAgICAgICAgICByYW5rW2ldID0gc1tpXTsKICAgICAgICB9CgogICAgICAgIGZvciAoaW50IGxlbiA9IDE7IGxlbiA8IG47IGxlbiA8PD0gMSkgewogICAgICAgICAgICBtZW1jcHkociwgcmFuaywgbiAqIHNpemVvZihpbnQpKTsKICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICAgICAgICAgIHJhbmtbc2FbaV1dID0gKGkgPiAwICYmIHJbc2FbaSAtIDFdXSA9PSByW3NhW2ldXSAmJgogICAgICAgICAgICAgICAgICAgICAgICBzYVtpIC0gMV0gKyBsZW4gPCBuICYmIHJbc2FbaSAtIDFdICsgbGVuIC8gMl0gPT0gcltzYVtpXSArIGxlbiAvIDJdKQogICAgICAgICAgICAgICAgICAgICAgICA/IHJhbmtbc2FbaSAtIDFdXQogICAgICAgICAgICAgICAgICAgICAgICA6IGk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspCiAgICAgICAgICAgICAgICBjbnRbaV0gPSBpOwoKICAgICAgICAgICAgbWVtY3B5KHN0LCBzYSwgc2l6ZW9mKGludCkgKiBuKTsKICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICAgICAgICAgIGludCBzMSA9IHN0W2ldIC0gbGVuOwogICAgICAgICAgICAgICAgaWYgKHMxID49IDApCiAgICAgICAgICAgICAgICAgICAgc2FbY250W3JhbmtbczFdXSsrXSA9IHMxOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIHZvaWQgY2FsY19sY3AoKSB7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBuOyBpKyspCiAgICAgICAgICAgIHJhbmtbc2FbaV1dID0gaTsKICAgICAgICBmb3IgKGludCBpID0gMCwgaCA9IDA7IGkgPCBuOyBpKyspIHsKICAgICAgICAgICAgaWYgKHJhbmtbaV0gPCBuIC0gMSkgewogICAgICAgICAgICAgICAgaW50IGogPSBzYVtyYW5rW2ldICsgMV07CiAgICAgICAgICAgICAgICB3aGlsZShtYXgoaSwgaikgKyBoIDwgbiAmJiBzW2kgKyBoXSA9PSBzW2ogKyBoXSkKICAgICAgICAgICAgICAgICAgICArK2g7CiAgICAgICAgICAgICAgICBsY3BbcmFua1tpXSArIDFdID0gaDsKICAgICAgICAgICAgICAgIGlmIChoID4gMCkKICAgICAgICAgICAgICAgICAgICAtLWg7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGxvZ1RhYmxlWzBdID0gMDsKICAgICAgICBsb2dUYWJsZVsxXSA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDI7IGkgPCBuOyBpKyspCiAgICAgICAgICAgIGxvZ1RhYmxlW2ldID0gbG9nVGFibGVbaSA+PiAxXSArIDE7CgogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbjsgKytpKQogICAgICAgICAgICBybXFbMF1baV0gPSBsY3BbaV07CgogICAgICAgIGZvciAoaW50IGsgPSAxOyAoMSA8PCBrKSA8IG47ICsraykgewogICAgICAgICAgICBmb3IgKGludCBpID0gMDsgaSArICgxIDw8IGspIDw9IG47IGkrKykgewogICAgICAgICAgICAgICAgaW50IHggPSBybXFbayAtIDFdW2ldOwogICAgICAgICAgICAgICAgaW50IHkgPSBybXFbayAtIDFdW2kgKyAoMSA8PCBrIC0gMSldOwogICAgICAgICAgICAgICAgcm1xW2tdW2ldID0gbWluKHgsIHkpOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGludCBnZXRfbGNwKGludCBsLCBpbnQgcikgewogICAgICAgIGwgPSByYW5rW2xdOwogICAgICAgIHIgPSByYW5rW3JdOwogICAgICAgIGlmIChsID4gcikgewogICAgICAgICAgICBzd2FwKGwsIHIpOwogICAgICAgIH0KICAgICAgICBpZiAobCA9PSByKSB7CiAgICAgICAgICAgIHJldHVybiBuIC0gc2FbbF07CiAgICAgICAgfQogICAgICAgICsrbDsKICAgICAgICBpbnQgayA9IGxvZ1RhYmxlW3IgLSBsXTsKICAgICAgICBpbnQgeCA9IHJtcVtrXVtsXTsKICAgICAgICBpbnQgeSA9IHJtcVtrXVtyIC0gKDEgPDwgaykgKyAxXTsKICAgICAgICByZXR1cm4gbWluKHgsIHkpOwogICAgfQp9OwoKCm5hbWVzcGFjZSBobGQgewogICAgdmVjdG9yIDxpbnQ+IGdbTUFYTl07CiAgICBpbnQgc3pbTUFYTl07CiAgICBpbnQgcFtNQVhOXTsKCiAgICBpbnQgcG9zX3VwW01BWE5dOwogICAgaW50IHBvc19kb3duW01BWE5dOwoKICAgIGludCByW01BWE5dOwogICAgaW50IHJvb3RbTUFYTl07CiAgICBpbnQgcnRbTUFYTl07CgogICAgaW50IHRpbltNQVhOXTsKICAgIGludCB0b3V0W01BWE5dOwogICAgaW50IHRpbWVyID0gMDsKCiAgICBpbnQgcG9zW01BWE5dOwoKICAgIHZlY3RvciA8aW50PiBjW01BWE5dOwoKICAgIGludCBwYXRoQ291bnQgPSAwOwoKICAgIHZvaWQgZGZzKGludCB2LCBpbnQgcGFyKSB7CiAgICAgICAgcFt2XSA9IHBhcjsKICAgICAgICBzelt2XSA9IDE7CiAgICAgICAgdGluW3ZdID0gdGltZXIrKzsKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IChpbnQpZ1t2XS5zaXplKCk7ICsraSkgewogICAgICAgICAgICBpbnQgdG8gPSBnW3ZdW2ldOwogICAgICAgICAgICBpZiAodG8gPT0gcGFyKSB7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBkZnModG8sIHYpOwogICAgICAgICAgICBzelt2XSArPSBzelt0b107CiAgICAgICAgfQogICAgICAgIHRvdXRbdl0gPSB0aW1lcisrOwogICAgfQoKICAgIHZvaWQgZGVjb21wKGludCB2LCBpbnQgcGFyLCBpbnQgaykgewogICAgICAgIHBvc1t2XSA9IGNba10uc2l6ZSgpOwogICAgICAgIGNba10ucHVzaF9iYWNrKHYpOwogICAgICAgIHJvb3Rbdl0gPSBydFtrXTsKICAgICAgICByW3ZdID0gazsKCiAgICAgICAgaW50IHggPSAwLCB5ID0gLTE7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCAoaW50KWdbdl0uc2l6ZSgpOyArK2kpIHsKICAgICAgICAgICAgaW50IHRvID0gZ1t2XVtpXTsKICAgICAgICAgICAgaWYgKHRvID09IHBhcikKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICBpZiAoc3pbdG9dID4geCkgewogICAgICAgICAgICAgICAgeCA9IHN6W3RvXTsKICAgICAgICAgICAgICAgIHkgPSB0bzsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoeSAhPSAtMSkgZGVjb21wKHksIHYsIGspOwoKICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IChpbnQpZ1t2XS5zaXplKCk7ICsraSkgewogICAgICAgICAgICBpbnQgdG8gPSBnW3ZdW2ldOwogICAgICAgICAgICBpZiAodG8gIT0gcGFyICYmIHRvICE9IHkpIHsKICAgICAgICAgICAgICAgIHJ0W3BhdGhDb3VudF0gPSB0bzsKICAgICAgICAgICAgICAgIGRlY29tcCh0bywgdiwgcGF0aENvdW50KyspOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQogICAgdm9pZCBpbml0U0EoY2hhciAqIHMsIGNoYXIgKiBkYXRhKSB7CiAgICAgICAgaW50IGxlbiA9IDA7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCBwYXRoQ291bnQ7ICsraSkgewogICAgICAgICAgICBmb3IgKGludCBqID0gMDsgaiA8IChpbnQpY1tpXS5zaXplKCk7ICsraikgewogICAgICAgICAgICAgICAgaW50IHYgPSBjW2ldW2pdOwogICAgICAgICAgICAgICAgc1twb3NfZG93blt2XSA9IGxlbisrXSA9IGRhdGFbdl07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZm9yIChpbnQgaiA9IChpbnQpY1tpXS5zaXplKCkgLSAxOyBqID49IDA7IC0taikgewogICAgICAgICAgICAgICAgaW50IHYgPSBjW2ldW2pdOwogICAgICAgICAgICAgICAgc1twb3NfdXBbdl0gPSBsZW4rK10gPSBkYXRhW3ZdOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQoKICAgIGlubGluZSBib29sIHVwcGVyKGludCBhLCBpbnQgYikgewogICAgICAgIHJldHVybiB0aW5bYV0gPD0gdGluW2JdICYmIHRvdXRbYV0gPj0gdG91dFtiXTsKICAgIH0KICAgIHBhaXIgPGludCwgaW50PiB1cFtMT0ddOwogICAgcGFpciA8aW50LCBpbnQ+IGRvd25bTE9HXTsKCiAgICBpbnQgZ2V0SGVhdnlTZWdtZW50cyhpbnQgYSwgaW50IGIsIHBhaXIgPGludCwgaW50PiAqIHJlcykgewogICAgICAgIGludCBzdXAgPSAwOwogICAgICAgIGludCBzZG93biA9IDA7CgogICAgICAgIHdoaWxlICghdXBwZXIocm9vdFthXSwgYikpIHsKICAgICAgICAgICAgdXBbc3VwKytdID0gbWFrZV9wYWlyKHBvc191cFthXSwgcG9zX3VwW3Jvb3RbYV1dKTsKICAgICAgICAgICAgYSA9IHBbcm9vdFthXV07CiAgICAgICAgfQogICAgICAgIHdoaWxlICghdXBwZXIocm9vdFtiXSwgYSkpIHsKICAgICAgICAgICAgZG93bltzZG93bisrXSA9IG1ha2VfcGFpcihwb3NfZG93bltyb290W2JdXSwgcG9zX2Rvd25bYl0pOwogICAgICAgICAgICBiID0gcFtyb290W2JdXTsKICAgICAgICB9CiAgICAgICAgYXNzZXJ0KHJbYV0gPT0gcltiXSk7CiAgICAgICAgaWYgKHVwcGVyKGEsIGIpKSB7CiAgICAgICAgICAgIGRvd25bc2Rvd24rK10gPSBtYWtlX3BhaXIocG9zX2Rvd25bYV0sIHBvc19kb3duW2JdKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB1cFtzdXArK10gPSBtYWtlX3BhaXIocG9zX3VwW2FdLCBwb3NfdXBbYl0pOwogICAgICAgIH0KICAgICAgICBmb3IgKGludCBpID0gMDsgaSA8IHN1cDsgKytpKSB7CiAgICAgICAgICAgICpyZXMrKyA9IHVwW2ldOwogICAgICAgIH0KICAgICAgICBmb3IgKGludCBpID0gc2Rvd24gLSAxOyBpID49IDA7IC0taSkgewogICAgICAgICAgICAqcmVzKysgPSBkb3duW2ldOwogICAgICAgIH0KICAgICAgICByZXR1cm4gc3VwICsgc2Rvd247CiAgICB9Cn0KCmludCBtYWluKCkgewojaWZkZWYgTE9DQUwKICAgIGZyZW9wZW4oImlucHV0LnR4dCIsICJyIiwgc3RkaW4pOwojZWxzZQoKI2VuZGlmCiAgICBpb3NfYmFzZTo6c3luY193aXRoX3N0ZGlvKGZhbHNlKTsKCiAgICBpbnQgbjsKICAgIHNjYW5mKCIlZCIsICZuKTsKCiAgICBjaGFyIGRhdGFbbiArIDFdOwogICAgc2NhbmYoIiVzIiwgZGF0YSk7CgogICAgZm9yIChpbnQgaSA9IDA7IGkgKyAxIDwgbjsgKytpKSB7CiAgICAgICAgaW50IGEsIGI7CiAgICAgICAgc2NhbmYoIiVkJWQiLCAmYSwgJmIpOwogICAgICAgIC0tYSwgLS1iOwogICAgICAgIGhsZDo6Z1thXS5wdXNoX2JhY2soYik7CiAgICAgICAgaGxkOjpnW2JdLnB1c2hfYmFjayhhKTsKICAgIH0KCiAgICBobGQ6OmRmcygwLCAtMSk7CiAgICBobGQ6OmRlY29tcCgwLCAtMSwgaGxkOjpwYXRoQ291bnQrKyk7CiAgICBobGQ6OmluaXRTQShzdWZfYXJyYXk6OnMsIGRhdGEpOwoKICAgIHN1Zl9hcnJheTo6biA9IDIgKiBuOwogICAgc3VmX2FycmF5Ojpwcm9jZXNzKCk7CiAgICBzdWZfYXJyYXk6OmNhbGNfbGNwKCk7CgogICAgaW50IG07CiAgICBzY2FuZigiJWQiLCAmbSk7CgogICAgcGFpciA8aW50LCBpbnQ+IHNlZ3NMW0xPR107CiAgICBwYWlyIDxpbnQsIGludD4gc2Vnc1JbTE9HXTsKCiAgICB3aGlsZSAobS0tKSB7CiAgICAgICAgaW50IGEsIGIsIGMsIGQ7CiAgICAgICAgc2NhbmYoIiVkJWQlZCVkIiwgJmEsICZiLCAmYywgJmQpOwogICAgICAgIC0tYSwgLS1iLCAtLWMsIC0tZDsKCiAgICAgICAgaW50IGxzaXplID0gaGxkOjpnZXRIZWF2eVNlZ21lbnRzKGEsIGIsIHNlZ3NMKTsKCiAgICAgICAgaW50IHJzaXplID0gaGxkOjpnZXRIZWF2eVNlZ21lbnRzKGMsIGQsIHNlZ3NSKTsKCiAgICAgICAgaW50IGkgPSAwLCBqID0gMDsKICAgICAgIGludCBsZW4gPSAwOwogICAgICAgd2hpbGUgKGkgPCBsc2l6ZSAmJiBqIDwgcnNpemUpIHsKICAgICAgICAgICBpbnQgbGNwID0gc3VmX2FycmF5OjpnZXRfbGNwKHNlZ3NMW2ldLmZpcnN0LCBzZWdzUltqXS5maXJzdCk7CiAgICAgICAgICAgbGNwID0gbWluKGxjcCwgc2Vnc0xbaV0uc2Vjb25kIC0gc2Vnc0xbaV0uZmlyc3QgKyAxKTsKICAgICAgICAgICBsY3AgPSBtaW4obGNwLCBzZWdzUltqXS5zZWNvbmQgLSBzZWdzUltqXS5maXJzdCArIDEpOwogICAgICAgICAgIGxlbiArPSBsY3A7CiAgICAgICAgICAgc2Vnc0xbaV0uZmlyc3QgKz0gbGNwOwogICAgICAgICAgIHNlZ3NSW2pdLmZpcnN0ICs9IGxjcDsKCiAgICAgICAgICAgYm9vbCBvayA9IGZhbHNlOwoKICAgICAgICAgICBpZiAoc2Vnc0xbaV0uZmlyc3QgPiBzZWdzTFtpXS5zZWNvbmQpIHsKICAgICAgICAgICAgICAgKytpOwogICAgICAgICAgICAgICBvayA9IHRydWU7CiAgICAgICAgICAgfQoKICAgICAgICAgICBpZiAoc2Vnc1Jbal0uZmlyc3QgPiBzZWdzUltqXS5zZWNvbmQpIHsKICAgICAgICAgICAgICAgKytqOwogICAgICAgICAgICAgICBvayA9IHRydWU7CiAgICAgICAgICAgfQoKICAgICAgICAgICBpZiAoIW9rKSB7CiAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgIH0KICAgICAgIH0KICAgICAgICBwcmludGYoIiVkXG4iLCBsZW4pOwogICAgfQoKI2lmZGVmIExPQ0FMCiAgICBjZXJyIDw8ICJUaW1lIGVsYXBzZWQ6ICIgPDwgKGRvdWJsZSljbG9jaygpIC8gQ0xPQ0tTX1BFUl9TRUMgKiAxMDAwIDw8ICIgbXMuXG4iOwojZW5kaWYgLy8gTE9DQUwKICAgIHJldHVybiAwOwp9