解説付き
const int MO = (int)1e9 + 7;
string S[2001];
RollingHash rh[2001];
int f[2001][2001];
mint ans[2001], fact[2001];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int N;
cin >> N;
rep(i, N) {
cin >> S[i];
}
sort(S, S + N);
rep(i, N) {
rh[i] = RollingHash(S[i]);
}
rep(i, N)rep(j, N) {
if (i == j)f[i][j] = 1;
else if (i > j)f[i][j] = f[j][i];
else {
int ok = 0, ng = min(sz(S[i]), sz(S[j])) + 1, mid;
while (ng - ok > 1) {
mid = (ok + ng) / 2;
(rh[i].getHash(0, mid) == rh[j].getHash(0, mid) ? ok : ng) = mid;
}
f[i][j] = ng;
}
}
f[N - 1][N] = 1;
auto C = combinations(N + 10, MO);
for (int ba = 1; ba <= N; ++ba) {
mint sm;
for (int a = 0; a + ba < N; ++a) {
sm += max(f[a][a + ba], f[a + ba][a + ba + 1]);
}
for (int K = ba; K <= N - 1; ++K) {
if (ba != N)ans[K - 1] += sm * C[N - ba - 1][K - ba];
}
}
for (int b = 0; b < N; ++b) {
for (int K = b+1; K <= N; ++K) {
ans[K - 1] += mint(f[b][b + 1]) * C[N - b - 1][K - b - 1];
}
}
fact[0] = 1;
rep(i, N)fact[i + 1] = fact[i] * (i + 1);
rep(i, N)cout << ans[i] * fact[i + 1] << endl;
}