/*
  Copyright 2013 Marek "p2004a" Rusinowski
  Aho-Corasick algorithm
*/
#include <cstdio>
#include <vector>
#include <string>
#include <deque>

#define MAXN 1000000

using namespace std;

class PatternsMatcher {
  class TrieNode {
   public:
    static int it;
    TrieNode *son[26];
    int num;
    TrieNode *fail;
    
    TrieNode() : num(0), fail(NULL) {
      for (int i = 0; i < 26; ++i) son[i] = NULL;
    }
    
    TrieNode(const char *str) : num(0), fail(NULL) {
      for (int i = 0; i < 26; ++i) son[i] = NULL;
      if (*str != '\0') son[*str - 'a'] = new TrieNode(str + 1);
      else num = ++it;
    }
    
    ~TrieNode() {
      for (int i = 0; i < 26; ++i) delete son[i];
    }
    
    void add(const char *str) {
      if (*str == '\0') num = ++it;
      else if (son[*str - 'a'] == NULL) son[*str - 'a'] = new TrieNode(str + 1);
      else son[*str - 'a']->add(str + 1);
    }
  };
  
  TrieNode root;
  bool fail_ok;
  
  void compute_fail() {
    root.fail = &root;
    deque<TrieNode*> q;
    q.push_back(&root);
    while (!q.empty()) {
      TrieNode *v = q.front();
      q.pop_front();
      for (int i = 0; i < 26; ++i) {
        if (v->son[i] != NULL) {
          q.push_back(v->son[i]);
          TrieNode *tmp = v->fail;
          while (tmp != &root && tmp->son[i] == NULL) tmp = tmp->fail;
          v->son[i]->fail = tmp->son[i] != NULL && tmp->son[i] != v->son[i] ? tmp->son[i] : &root;
        }
      }
    }
  }
  
 public:
  PatternsMatcher() : fail_ok(false) {}
 
  void add_pattern(const char *str) {
    root.add(str);
    fail_ok = false;
  }
  
  void search(const char *str, bool (*callback)(int idx, int pat_idx, void *data), void *data = NULL) {
    if (!fail_ok) compute_fail();
    fail_ok = true;
    TrieNode *v = &root;
    bool stop = false;
    for (int i = 0; *str != '\0' && !stop; ++i, ++str) {
      int j = *str - 'a';
      while (v != &root && v->son[j] == NULL) v = v->fail;
      v = v->son[j] != NULL ? v->son[j] : &root;
      for (TrieNode *u = v; u != &root; u = u->fail) {
        if (u->num > 0 && !callback(i, u->num - 1, data)) {
          stop = true;
          break;
        }
      }
    }
  }
  
  /*
  This function creates an input for Graphviz dot representing a Trie structure.
  Useful while debugging. Maybe it will be useful while hacking the code
  
  void print(FILE *file) {
    deque<deque<TrieNode *> > rank;
    rank.push_back(deque<TrieNode *>());
    rank[0].push_back(&root);
    deque<pair<TrieNode*, unsigned> > q;
    q.push_back(make_pair(&root, 0));
    fprintf(file, "digraph trie {\n");
    while (!q.empty()) {
      pair<TrieNode*, unsigned> p = q.front();
      q.pop_front();
      if (p.first->fail != NULL) {
        fprintf(file, "  \"%p\" -> \"%p\" [style=\"dashed\"];\n", p.first, p.first->fail);
      }
      for (unsigned i = 0; i < 26; ++i) {
        if (p.first->son[i] != NULL) {
          q.push_back(make_pair(p.first->son[i], p.second + 1));
          if (rank.size() == p.second + 1) rank.push_back(deque<TrieNode *>());
          rank.back().push_back(p.first->son[i]);
          fprintf(file, "  \"%p\" -> \"%p\" [label=\" %c\"];\n", p.first, p.first->son[i], i + 'a');
        }
      }
    }
    for (unsigned i = 0; i < rank.size(); ++i) {
      fprintf(file, "  {rank=same; ");
      for (unsigned j = 0; j < rank[i].size(); ++j) {
        fprintf(file, "\"%p\" ", rank[i][j]);
      }
      fprintf(file, "}\n");
    }
    fprintf(file, "}\n");
    fflush(file);
  }*/
};
int PatternsMatcher::TrieNode::it = 0;

bool f(int i, int idx, void *data) {
  vector<string> &t = *((vector<string> *) data);
  printf("%s%s\n", string(i - t[idx].size() + 1, ' ').c_str(), t[idx].c_str());
  return true;
}

int main() {
  char *str = new char [MAXN];
  int n;
  scanf("%d\n", &n);
  PatternsMatcher x;
  vector<string> t;
  for (int i = 0; i < n; ++i) {
    scanf("%s\n", str);
    x.add_pattern(str);
    t.push_back(str);
  }
  scanf("%s\n", str);
  printf("%s\n", str);
  x.search(str, f, &t);
  delete str;
  return 0;
}
