/**
 * Trie - a tree for keeping a set of words, factoring out duplicate prefixes.
 * Demo application - keep a sorted set of words.
 *
 * INPUT: a list of words.
 * OUTPUT: the same list, sorted and without duplicates.
 * 
 * Author: Erel Segal
 * Created: 2010-10-14
 */

#include <map>
#include <string>
#include <iostream>
using namespace std;


class Trie;
typedef Trie* PTrieNode;

class Trie {
  map<char,PTrieNode> myChildren;
  bool isWordEnd;  // "true" if a word ends in this node

public:
  
  Trie(): isWordEnd(false) {}

  /* recursively add a single word to the node */
  void add (const char* newWord) {
    char first = newWord[0];
    if (!first) { // empty word
      isWordEnd = true;
    } else {
      if (!myChildren[first]) {
        myChildren[first] = new Trie();
      }
      myChildren[first]->add(newWord+1);
    }
  }

  /* recursively print all words in the node in order */
  void print (ostream& out, string prefix) const {
    if (isWordEnd) {
      out << prefix << " ";
    }

    map<char,PTrieNode>::const_iterator it;
    for (it=myChildren.begin() ; it!=myChildren.end(); it++) {
      char c = (*it).first;
      PTrieNode child = (*it).second;
      child->print(out, prefix+c);
    }
  }

  friend ostream& operator<< (ostream& out, const Trie& node) {
    node.print(out, /*prefix=*/"");
    return out;
  }
};



int main() {
  Trie t;
  string word;
  while (!cin.eof()) {
    cin >> word;
    t.add(word.c_str());
    cout << t << endl;
  }
}


