#include <bits/stdc++.h>
#define ll long long
#define fast ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define pii pair<int,int>
#define pli pair<ll,int>
#define pil pair<int,ll>
#define pll pair<ll,ll>
#define fi first
#define se second
#define MASK(i) (1ll<<i)
#define bit(mask,i) ((mask>>i)&1)
#define el '\n'
#define debug cout << "NOBUG" << endl;
#define pb push_back
#define ALL(vec) vec.begin(),vec.end()
#define File(NAME) freopen(NAME".inp" , "r" , stdin); freopen(NAME".out", "w" , stdout);
using namespace std;
const int mod = 1e9+7 , oo = 0x3f3f3f3f;
const ll ooll = 0x3f3f3f3f3f3f3f3f;
template <class X , class Y>
bool maximize(X &x , Y y) {
if(x < y) {
x = y;
return true;
}
return false;
}
template <class X , class Y>
bool minimize(X &x , Y y) {
if(x > y) {
x = y;
return true;
}
return false;
}
template <class X , class Y>
void add_mod(X &x , Y y , int mod) {
x += y;
if(x >= mod) x-=mod;
if(x < 0) x += mod;
}
const int NUMBER_OF_NODES = 1e6+5;
struct Node {
int child[26] , next[26];
int fail;
vector <int> found;
}node[NUMBER_OF_NODES];
struct AC {
int curCnt = 0;
inline int newNode() {
curCnt++;
Node &curNode = node[curCnt];
for(int c = 0 ; c < 26 ; c++) {
curNode.child[c] = -1;
curNode.next[c] = -1;
}
curNode.fail = -1;
curNode.found.clear();
return curCnt;
}
int root = newNode();
void add(string s , int id) {
int p = root;
for(char c : s) {
if(node[p].child[c-'a'] == -1) node[p].child[c-'a'] = newNode();
p = node[p].child[c-'a'];
}
node[p].found.pb(id);
}
void bfs() {
node[root].fail = root;
for(int c = 0 ; c < 26 ; c++) {
node[root].next[c] = (node[root].child[c] != -1 ? node[root].child[c] : root);
}
queue <int> q;
q.push(root);
while(q.size()) {
int u = q.front();q.pop();
for(int c = 0 ; c < 26 ; c++)if(node[u].child[c] != -1) {
int v = node[u].child[c];
node[v].fail = (u == root ? root : node[node[u].fail].next[c]);
for(int c = 0 ; c < 26 ; c++) {
node[v].next[c] = (node[v].child[c] != -1 ? node[v].child[c] : node[node[v].fail].next[c]);
}
for(int x : node[node[v].fail].found) {
node[v].found.pb(x);
}
q.push(v);
}
}
}
}Aho;
// found do not very necessary , if you have to count the number of appearance of Si , just do back dfs like in kmp
// i do not sure about if found can cause mle to my code , so just do not use it
// it is so risky
int main() {
fast
File("TASK");
int n; cin >> n;
for(int i = 1 ; i <= n ; i++) {
string s; cin >> s;
Aho.add(s , i);
}
Aho.bfs();
string t; cin >> t;
int p = Aho.root;
for(int i = 0 ; i < t.size(); i++) {
int c = t[i]-'a';
p = node[p].next[c];
cout << p << ':';
for(int x : node[p].found) cout << x << ' ';
cout << el;
}
return 0;
}
/*
input:
6
di
du
didu
dudua
duadi
didi
diduduadi
output:
2|
3|1
5|
6|3 2
7|
8|2
9|4
11|
12|5 1
*/
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CiNkZWZpbmUgbGwgbG9uZyBsb25nCiNkZWZpbmUgZmFzdCBpb3NfYmFzZTo6c3luY193aXRoX3N0ZGlvKGZhbHNlKTtjaW4udGllKG51bGxwdHIpO2NvdXQudGllKG51bGxwdHIpOwojZGVmaW5lIHBpaSBwYWlyPGludCxpbnQ+CiNkZWZpbmUgcGxpIHBhaXI8bGwsaW50PgojZGVmaW5lIHBpbCBwYWlyPGludCxsbD4KI2RlZmluZSBwbGwgcGFpcjxsbCxsbD4KI2RlZmluZSBmaSBmaXJzdAojZGVmaW5lIHNlIHNlY29uZAojZGVmaW5lIE1BU0soaSkgKDFsbDw8aSkKI2RlZmluZSBiaXQobWFzayxpKSAoKG1hc2s+PmkpJjEpCiNkZWZpbmUgZWwgJ1xuJwojZGVmaW5lIGRlYnVnIGNvdXQgPDwgIk5PQlVHIiA8PCBlbmRsOwojZGVmaW5lIHBiIHB1c2hfYmFjawojZGVmaW5lIEFMTCh2ZWMpIHZlYy5iZWdpbigpLHZlYy5lbmQoKQojZGVmaW5lIEZpbGUoTkFNRSkgZnJlb3BlbihOQU1FIi5pbnAiICwgInIiICwgc3RkaW4pOyBmcmVvcGVuKE5BTUUiLm91dCIsICJ3IiAsIHN0ZG91dCk7Cgp1c2luZyBuYW1lc3BhY2Ugc3RkOwpjb25zdCBpbnQgbW9kID0gMWU5KzcgLCBvbyA9IDB4M2YzZjNmM2Y7CmNvbnN0IGxsIG9vbGwgPSAweDNmM2YzZjNmM2YzZjNmM2Y7Cgp0ZW1wbGF0ZSA8Y2xhc3MgWCAsIGNsYXNzIFk+CmJvb2wgbWF4aW1pemUoWCAmeCAsIFkgeSkgewogICAgaWYoeCA8IHkpIHsKICAgICAgICB4ID0geTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKfQp0ZW1wbGF0ZSA8Y2xhc3MgWCAsIGNsYXNzIFk+CmJvb2wgbWluaW1pemUoWCAmeCAsIFkgeSkgewogICAgaWYoeCA+IHkpIHsKICAgICAgICB4ID0geTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKfQp0ZW1wbGF0ZSA8Y2xhc3MgWCAsIGNsYXNzIFk+CnZvaWQgYWRkX21vZChYICZ4ICwgWSB5ICwgaW50IG1vZCkgewogICAgeCArPSB5OwogICAgaWYoeCA+PSBtb2QpIHgtPW1vZDsKICAgIGlmKHggPCAwKSB4ICs9IG1vZDsKfQoKY29uc3QgaW50IE5VTUJFUl9PRl9OT0RFUyA9IDFlNis1OwoKc3RydWN0IE5vZGUgewogICAgaW50IGNoaWxkWzI2XSAsIG5leHRbMjZdOwogICAgaW50IGZhaWw7CiAgICB2ZWN0b3IgPGludD4gZm91bmQ7Cn1ub2RlW05VTUJFUl9PRl9OT0RFU107CgpzdHJ1Y3QgQUMgewogICAgaW50IGN1ckNudCA9IDA7CiAgICBpbmxpbmUgaW50IG5ld05vZGUoKSB7CiAgICAgICAgY3VyQ250Kys7CgogICAgICAgIE5vZGUgJmN1ck5vZGUgPSBub2RlW2N1ckNudF07CgogICAgICAgIGZvcihpbnQgYyA9IDAgOyBjIDwgMjYgOyBjKyspIHsKICAgICAgICAgICAgY3VyTm9kZS5jaGlsZFtjXSA9IC0xOwogICAgICAgICAgICBjdXJOb2RlLm5leHRbY10gPSAtMTsKICAgICAgICB9CiAgICAgICAgY3VyTm9kZS5mYWlsID0gLTE7CiAgICAgICAgY3VyTm9kZS5mb3VuZC5jbGVhcigpOwoKICAgICAgICByZXR1cm4gY3VyQ250OwogICAgfQoKICAgIGludCByb290ID0gbmV3Tm9kZSgpOwoKICAgIHZvaWQgYWRkKHN0cmluZyBzICwgaW50IGlkKSB7CiAgICAgICAgaW50IHAgPSByb290OwogICAgICAgIGZvcihjaGFyIGMgOiBzKSB7CiAgICAgICAgICAgIGlmKG5vZGVbcF0uY2hpbGRbYy0nYSddID09IC0xKSBub2RlW3BdLmNoaWxkW2MtJ2EnXSA9IG5ld05vZGUoKTsKICAgICAgICAgICAgcCA9IG5vZGVbcF0uY2hpbGRbYy0nYSddOwogICAgICAgIH0KICAgICAgICBub2RlW3BdLmZvdW5kLnBiKGlkKTsKICAgIH0KCiAgICB2b2lkIGJmcygpIHsKICAgICAgICBub2RlW3Jvb3RdLmZhaWwgPSByb290OwogICAgICAgIGZvcihpbnQgYyA9IDAgOyBjIDwgMjYgOyBjKyspIHsKICAgICAgICAgICAgbm9kZVtyb290XS5uZXh0W2NdID0gKG5vZGVbcm9vdF0uY2hpbGRbY10gIT0gLTEgPyBub2RlW3Jvb3RdLmNoaWxkW2NdIDogcm9vdCk7CiAgICAgICAgfQoKICAgICAgICBxdWV1ZSA8aW50PiBxOwogICAgICAgIHEucHVzaChyb290KTsKCiAgICAgICAgd2hpbGUocS5zaXplKCkpIHsKICAgICAgICAgICAgaW50IHUgPSBxLmZyb250KCk7cS5wb3AoKTsKCiAgICAgICAgICAgIGZvcihpbnQgYyA9IDAgOyBjIDwgMjYgOyBjKyspaWYobm9kZVt1XS5jaGlsZFtjXSAhPSAtMSkgewogICAgICAgICAgICAgICAgaW50IHYgPSBub2RlW3VdLmNoaWxkW2NdOwoKICAgICAgICAgICAgICAgIG5vZGVbdl0uZmFpbCA9ICh1ID09IHJvb3QgPyByb290IDogbm9kZVtub2RlW3VdLmZhaWxdLm5leHRbY10pOwogICAgICAgICAgICAgICAgZm9yKGludCBjID0gMCA7IGMgPCAyNiA7IGMrKykgewogICAgICAgICAgICAgICAgICAgIG5vZGVbdl0ubmV4dFtjXSA9IChub2RlW3ZdLmNoaWxkW2NdICE9IC0xID8gbm9kZVt2XS5jaGlsZFtjXSA6IG5vZGVbbm9kZVt2XS5mYWlsXS5uZXh0W2NdKTsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBmb3IoaW50IHggOiBub2RlW25vZGVbdl0uZmFpbF0uZm91bmQpIHsKICAgICAgICAgICAgICAgICAgICBub2RlW3ZdLmZvdW5kLnBiKHgpOwogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIHEucHVzaCh2KTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KfUFobzsKCi8vIGZvdW5kIGRvIG5vdCB2ZXJ5IG5lY2Vzc2FyeSAsIGlmIHlvdSBoYXZlIHRvIGNvdW50IHRoZSBudW1iZXIgb2YgYXBwZWFyYW5jZSBvZiBTaSAsIGp1c3QgZG8gYmFjayBkZnMgbGlrZSBpbiBrbXAKLy8gaSBkbyBub3Qgc3VyZSBhYm91dCBpZiBmb3VuZCBjYW4gY2F1c2UgbWxlIHRvIG15IGNvZGUgLCBzbyBqdXN0IGRvIG5vdCB1c2UgaXQKLy8gaXQgaXMgc28gcmlza3kKCmludCBtYWluKCkgewogICAgZmFzdAogICAgRmlsZSgiVEFTSyIpOwogICAgaW50IG47IGNpbiA+PiBuOwogICAgZm9yKGludCBpID0gMSA7IGkgPD0gbiA7IGkrKykgewogICAgICAgIHN0cmluZyBzOyBjaW4gPj4gczsKICAgICAgICBBaG8uYWRkKHMgLCBpKTsKICAgIH0KCiAgICBBaG8uYmZzKCk7CgogICAgc3RyaW5nIHQ7IGNpbiA+PiB0OwogICAgaW50IHAgPSBBaG8ucm9vdDsKICAgIGZvcihpbnQgaSA9IDAgOyBpIDwgdC5zaXplKCk7IGkrKykgewogICAgICAgIGludCBjID0gdFtpXS0nYSc7CiAgICAgICAgcCA9IG5vZGVbcF0ubmV4dFtjXTsKICAgICAgICBjb3V0IDw8IHAgPDwgJzonOwogICAgICAgIGZvcihpbnQgeCA6IG5vZGVbcF0uZm91bmQpIGNvdXQgPDwgeCA8PCAnICc7CiAgICAgICAgY291dCA8PCBlbDsKICAgIH0KICAgIHJldHVybiAwOwp9Ci8qCmlucHV0Ogo2CmRpCmR1CmRpZHUKZHVkdWEKZHVhZGkKZGlkaQpkaWR1ZHVhZGkKb3V0cHV0OgoyfAozfDEKNXwKNnwzIDIKN3wKOHwyCjl8NAoxMXwKMTJ8NSAxCiovCg==