intinsert(std::string str){ int p = 1; for (char ch : str) { int v = ch - 'a'; if (!t[p].trans[v]) { int np = ++ nodeCount; t[p].trans[v] = np; t[np].length = t[p].length + 1; ans1[np] = -inf; } p = t[p].trans[v]; } flag[p] = 1; return p; }
voidbuild_fail(){ for (int i = 0; i < 26; i ++) { t[0].trans[i] = 1; } t[1].fail = 0;
std::queue<int> q; q.push(1);
while (q.size()) { int u = q.front(); q.pop(); for (int i = 0; i < 26; i ++) { if (t[u].trans[i]) { t[t[u].trans[i]].fail = t[t[u].fail].trans[i]; q.push(t[u].trans[i]); } else { t[u].trans[i] = t[t[u].fail].trans[i]; } } } }
voiddfs_init(int u){ up[u] = flag[u] ? u : up[t[u].fail]; for (int v : son[u]) { dfs_init(v); } } voidbuild_tree(){ for (int i = 2; i <= nodeCount; i ++) { son[t[i].fail].push_back(i); } dfs_init(1); }
voidpush(int p, int r){ while (up[p]) { p = up[p]; upd(p, r);
for (int i = 1; i <= n; i ++) { std::cin >> a[i]; }
for (int i = 1; i <= n; i ++) { sum[i] = sum[i - 1] + a[i]; ssum[i] = (ssum[i - 1] + sum[i]) % mod; if (ssum[i] < 0) { ssum[i] += mod; } }
for (int i = 1; i <= n; i ++) { pre[i] = std::max(pre[i - 1] + a[i], 0LL); } for (int i = n; i >= 1; i --) { suf[i] = std::max(suf[i + 1] + a[i], 0LL); }
for (int i = 1; i <= Q; i ++) { std::string t; std::cin >> t; belong[i] = AC::insert(t); }
AC::build_fail(); AC::build_tree();
int p = 1; for (int i = 1; i <= n; i ++) { p = AC::t[p].trans[str[i] - 'a']; AC::push(p, i); }
for (int i = 1; i <= Q; i ++) { int p = belong[i]; std::cout << AC::ans1[p] << ' ' << AC::ans2[p] << '\n'; }