using namespace std;
struct node {
int fail;
int vis[30];
int end;
int lazy;
};
node ac[1000010];
int Map[2000],ans[20000],in[1000010],cnt;
void build(string s,int num) {
int p=0;
int len=s.size();
for(int i=0; i<len; i++) {
int c=s[i]-'a';
if(!ac[p].vis[c])ac[p].vis[c]=++cnt;
p=ac[p].vis[c];
}
if(!ac[p].end)ac[p].end=num;
Map[num]=ac[p].end;
}
void create(void) {
queue<int>q;
for(int i=0; i<26; i++) {
if(ac[0].vis[i]) {
ac[ac[0].vis[i]].fail=0;
q.push(ac[0].vis[i]);
}
}
while(!q.empty()) {
int u=q.front();
q.pop();
for(int i=0; i<26; i++) {
if(ac[u].vis[i]) {
ac[ac[u].vis[i]].fail=ac[ac[u].fail].vis[i];
q.push(ac[u].vis[i]);
in[ac[ac[u].fail].vis[i]]++;
} else ac[u].vis[i]=ac[ac[u].fail].vis[i];
}
}
}
void ask(string s) {
int p=0;
int len=s.size();
for(int i=0; i<len; i++) {
int c=s[i]-'a';
if(c==27){
ac[p].lazy=0;
continue;
}
ac[p].lazy++;
p=ac[p].vis[c];
}
}
void topo(){
queue<int>q;
for(int i=0;i<26;i++){
if(in[i]==0){
q.push(i);
}
}
while(!q.empty()){
int u=q.front();
q.pop();
int v=ac[u].fail;
ans[u]=ac[u].lazy;
in[v]--;
ac[v].lazy+=ac[u].lazy;
if(in[v]==0){
q.push(v);
}
}
}
string s,t;
int main() {
int n;
cin>>n;
for(int i=1; i<=n; i++) {
cin>>s;
// cout<<s<<endl;
t+=s+(char)('z'+1);
build(s,i);
}
create();
ask(t);
topo();
for(int i=1; i<=n; i++) {
cout<<ans[Map[i]]<<endl;
}
return 0;
}
拓扑排序优化 只过了样例