#include <iostream>
#include <iomanip>
#include <cmath>
#include <algorithm>
#include <bits/stdc++.h>
#include <set>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <map>
#define ll long long
using namespace __gnu_pbds;
using namespace std;
template <class T>
using ordered_set = tree<T , null_type , less<T> , rb_tree_tag , tree_order_statistics_node_update>;
// less<T>/greater<T> = ascending/descending.
// less_equal<>/greater_equal<> for ordered multiset
// ordered_multiset note : s.find(), s.erase() don't work + s.upper_bound() and s.lower_bound() swap jobs;
void fastIO(void) {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
}
int main(){
    fastIO();
    ll n; cin>>n;
    bool match;
    string temp;
    ll temp2;
    map<string,set<string>> names;
    for (int i = 0; i<n; i++){
        cin>>temp>>temp2;
        for (int j = 0; j<temp2; j++) {
            string temp3; cin>>temp3;
            names[temp].insert(temp3);
        }
    }
    for (auto i = names.begin(); i!=names.end(); i++) {
        for (auto it2 = i->second.begin(); it2!=i->second.end();){
            bool flag = 0;
            for (auto it3 = next(it2,1); it3!=i->second.end();) {
                bool flag2 = 0;
                bool match = 0;
                string str = *it2;
                string str2 = *it3;
                ll j = str.size()-1;
                ll k = str2.size()-1;
                while (j>=0 && k>=0) {
                    if (str[j]==str2[k]) {
                        if (j==0) {
                            flag = 1;
                            it2++;
                            i->second.erase(prev(it2,1));
                            match = 1;
                            break;
                        }
                        else if (k==0) {
                            flag2 = 1;
                            it3++;
                            i->second.erase(prev(it3,1));
                            match = 1;
                            break;
                        }
                        j--; k--;
                    }
                    else {
                        break;
                    }
                }
                if (!flag2) {
                    it3++;
                }
            }
            if (!flag) {
                it2++;
            }
        }
    }
    cout<<names.size()<<'\n';
    for (auto i = names.begin(); i!=names.end(); i++) {
        cout<<i->first<<' '<<i->second.size()<<' ';
        for (auto it2 = i->second.begin(); it2!=i->second.end(); it2++){
            cout<<*it2<<' ';
        }
        cout<<'\n';
    }
}
