#include <iostream>
#define ALPHABET_SIZE 26
using namespace std;
struct TrieNode
{
struct TrieNode *children[ALPHABET_SIZE];
bool isEndOfWord;
int elementCnt;
};
class Trie {
public:
/** Initialize your data structure here. */
struct TrieNode *head;
Trie() {
head = getNode();
}
TrieNode *getNode() {
struct TrieNode *pNode = new TrieNode;
pNode->isEndOfWord = false;
pNode->elementCnt = 0;
for (int i = 0; i < ALPHABET_SIZE; i++)
pNode->children[i] = NULL;
return pNode;
}
/** Inserts a word into the trie. */
void insert(string word) {
struct TrieNode *temp = head;
for(int i=0, idx; i < word.size(); ++i){
idx = word[i]-'a';
if(!temp->children[idx]){
temp->children[idx] = getNode();
++temp->elementCnt;
}
temp = temp->children[idx];
}
temp->isEndOfWord = true;
}
/** Returns if the word is in the trie. */
bool search(string word) {
struct TrieNode *temp = head;
for(int i=0, idx; i < word.size(); ++i){
idx = word[i]-'a';
if(!temp->children[idx])
return false;
temp = temp->children[idx];
}
return temp && temp->isEndOfWord;
}
/** Returns if there is any word in the trie that starts with the given prefix. */
bool startsWith(string prefix) {
struct TrieNode *temp = head;
for(int i=0; i < prefix.size(); ++i){
if(!temp->children[prefix[i]-'a'])
return false;
temp = temp->children[prefix[i]-'a'];
}
return true;
}
void commonPrefixes(struct TrieNode *rt){
for(int i = 0; i < ALPHABET_SIZE; ++i){
if(rt->children[i]){
cout<<(char)(i + 'a');
bool flag = rt->children[i]->elementCnt > 1 ||
rt->children[i]->isEndOfWord;
if(flag){
cout<<"\n";
// return;
}
else{
commonPrefixes(rt->children[i]);
}
}
}
}
void printWords(struct TrieNode *temp, char *a, int k){
if(temp->isEndOfWord){
cout<<a<<"\n";
}
for(int i=0; i<ALPHABET_SIZE; ++i){
if(temp->children[i]){
a[k] = i + 'a';
printWords(temp->children[i], a, k+1);
a[k+1] = '\0';
}
}
}
};
int main() {
// ios::sync_with_stdio(0);
// cin.tie(0);
int n; cin>>n;
string inp;
Trie* obj = new Trie();
for(int i=0; i<n; ++i){
cin>>inp;
obj->insert(inp);
}
cout<<"Common prefixes:\n";
obj->commonPrefixes(obj->head);
cout<<"*************************************************\n";
cout<<"Words in Trie:\n";
char a[200];
obj->printWords(obj->head, a, 0);
return 0;
}