#include <bits/stdc++.h>   const int N = 300010;   const int MOD = 1e9 + 7;   struct xxx {     int id;     char c;   } s[N];   std::string a, b, c;   int gap, n;   int sa[N], lcp[N], rank[N], tmp[N], bucket[N], cnt[N][3], ans[N], dp[19][N],       fw[N];   void update(int i, int v) {     while (i < N) {       fw[i] = (fw[i] + v) % MOD;       i += i & -i;     }   }   int query(int i) {     int res = 0;     while (i) {       res = (res + fw[i]) % MOD;       i -= i & -i;     }     if (res < 0) res += MOD;     return res;   }   int rmq(int f, int t) {     int k = 31 - __builtin_clz(t - f + 1);     int x = dp[k][f];     int y = dp[k][t - (1 << k) + 1];     if (lcp[x] < lcp[y]) return x;     return y;   }   void solve(int f, int t, int h) {     if (t - f + 1 < 3) return;     int m = rmq(f, t - 1);     int c0 = cnt[t][0] - cnt[f - 1][0];     int c1 = cnt[t][1] - cnt[f - 1][1];     int c2 = cnt[t][2] - cnt[f - 1][2];     int v = lcp[m];     int num = 1ll * c0 * c1 % MOD * c2 % MOD;     update(v + 1, -num);     update(h + 1, num);     solve(f, m, v);     solve(m + 1, t, v);   }   bool cmp2(int i, int j) {     i += gap;     j += gap;     if (i < n && j < n) return rank[i] < rank[j];     return i > j;   }   bool cmp(int i, int j) {     if (rank[i] != rank[j]) return rank[i] < rank[j];     i += gap;     j += gap;     if (i < n && j < n) return rank[i] < rank[j];     return i > j;   }   int main() {     std::cin >> a >> b >> c;     int an = int(a.size()), bn = int(b.size()), cn = int(c.size());     for (int i = 0; i < an; ++i) s[i].id = 0, s[i].c = a[i];     for (int i = 0; i < bn; ++i) s[i + an + 1].id = 1, s[i + an + 1].c = b[i];     for (int i = 0; i < cn; ++i)       s[i + an + bn + 2].id = 2, s[i + an + bn + 2].c = c[i];     s[an].c = 1;     s[an + bn + 1].c = 2;     n = an + bn + cn + 2;     int rn = 255;     for (int i = 0; i < n; ++i) {       sa[i] = i;       rank[i] = s[i].c;     }     for (gap = 1;; gap <<= 1) {       int p = 0;       for (int i = n - 1; i + gap >= n; --i) tmp[p++] = i;       std::fill(bucket, bucket + rn, 0);       for (int i = 0; i + gap < n; ++i) ++bucket[rank[i + gap]];       for (int i = 1; i < rn; ++i) bucket[i] += bucket[i - 1];       for (int i = 0; i + gap < n; ++i) tmp[--bucket[rank[i + gap]] + p] = i;       std::fill(bucket, bucket + rn, 0);       for (int i = 0; i < n; ++i) ++bucket[rank[i]];       for (int i = 1; i < rn; ++i) bucket[i] += bucket[i - 1];       for (int i = n - 1; i >= 0; --i) sa[--bucket[rank[tmp[i]]]] = tmp[i];       tmp[0] = 0;       for (int i = 1; i < n; ++i) tmp[i] = tmp[i - 1] + cmp(sa[i - 1], sa[i]);       for (int i = 0; i < n; ++i) rank[sa[i]] = tmp[i];       if (tmp[n - 1] == n - 1) break;       rn = tmp[n - 1] + 1;     }     for (int i = 0, k = 0; i < n; ++i) {       if (rank[i] == n - 1) continue;       for (int j = sa[rank[i] + 1]; s[i + k].c == s[j + k].c;) ++k;       lcp[rank[i]] = k;       if (k) --k;     }     for (int i = 0; i < n - 1; ++i) dp[0][i] = i;     for (int j = 1; 1 << j < n; ++j)       for (int i = 0; i + (1 << j) - 1 < n - 1; ++i) {         int x = dp[j - 1][i];         int y = dp[j - 1][i + (1 << (j - 1))];         dp[j][i] = lcp[x] < lcp[y] ? x : y;       }     assert(s[sa[0]].c == 1);     assert(s[sa[1]].c == 2);     for (int i = 2; i < n; ++i) {       cnt[i][0] = cnt[i - 1][0];       cnt[i][1] = cnt[i - 1][1];       cnt[i][2] = cnt[i - 1][2];       ++cnt[i][s[sa[i]].id];     }     int sz = std::min(an, std::min(bn, cn));     solve(2, n - 1, 0);     for (int i = 1; i <= sz; ++i) std::cout << query(i) <<    ;   }