#include <bits/stdc++.h>
#pragma GCC optimize("O3")
#pragma GCC target("sse4")
using namespace std;
using ii = pair<int, int>;
using ll = long long;
const int mod = 1e9 + 7;
const int N = 1e6 + 5;
const int M = 29;
int ans[N];
int dp[3][N];
struct suffixAutomaton {
  struct state {
    int len;
    int link;
    int next[M];
    ll cnt;
    bool terminal;
    state() {
      len = 0, link = -1, cnt = 0;
      terminal = false;
      for (int i = 0; i < M; i++) next[i] = -1;
    }
  };
  int get(char c) {
    if (c == '@') return 0;
    if (c == '#') return 1;
    if (c == '$') return 2;
    return 3 + c - 'a';
  }
  vector<state> st;
  int sz, last, l;
  char offset = 'a';
  suffixAutomaton() {}
  int pos[3];
  int getLen(int x) {
    if (~x) return st[x].len;
    return 0;
  }
  suffixAutomaton(string s) {
    int l = s.length();
    st.resize(2 * l);
    for (int i = 0; i < 2 * l; i++) st[i] = state();
    sz = 1, last = 0;
    st[0].len = 0;
    st[0].link = -1;
    for (int i = 0; i < l; i++) {
      addChar(get(s[i]));
    }
    for (int i = last; i != -1; i = st[i].link) st[i].terminal = true;
    vector<vector<int>> adj(2 * l);
    memset(dp, -1, sizeof dp);
    for (int i = 0; i < sz; i++) {
      ans[getLen(st[i].link) + 1] +=
          solve(0, i) * 1ll * solve(1, i) * 1ll * solve(2, i) % mod;
      ans[getLen(i) + 1] -=
          solve(0, i) * 1ll * solve(1, i) * 1ll * solve(2, i) % mod;
      if (ans[getLen(st[i].link) + 1] >= mod)
        ans[getLen(st[i].link) + 1] -= mod;
      if (ans[getLen(i) + 1] < 0) ans[getLen(i) + 1] += mod;
    }
  }
  int solve(int f, int idx) {
    if (idx == pos[f]) return 1;
    if (idx == pos[0] || idx == pos[1] || idx == pos[2]) return 0;
    int &ret = dp[f][idx];
    if (~ret) return ret;
    ret = 0;
    for (int i = 0; i < M; i++)
      if (~st[idx].next[i]) {
        ret += solve(f, st[idx].next[i]);
        if (ret >= mod) ret -= mod;
      }
    return ret;
  }
  void addChar(int c) {
    int cur = sz++;
    assert(cur < N * 2);
    if (c < 3) pos[c] = cur;
    st[cur].len = st[last].len + 1;
    st[cur].cnt = 1;
    int p = last;
    while (p != -1 and st[p].next[c] == -1) {
      st[p].next[c] = cur;
      p = st[p].link;
    }
    last = cur;
    if (p == -1) {
      st[cur].link = 0;
      return;
    }
    int q = st[p].next[c];
    if (st[q].len == st[p].len + 1) {
      st[cur].link = q;
      return;
    }
    int clone = sz++;
    for (int i = 0; i < M; i++) st[clone].next[i] = st[q].next[i];
    st[clone].link = st[q].link;
    st[clone].len = st[p].len + 1;
    st[clone].cnt = 0;
    while (p != -1 and st[p].next[c] == q) {
      st[p].next[c] = clone;
      p = st[p].link;
    }
    st[q].link = st[cur].link = clone;
    return;
  }
  bool contains(string &t) {
    int cur = 0;
    for (int i = 0; i < t.length(); i++) {
      cur = st[cur].next[t[i] - offset];
      if (cur == -1) return false;
    }
    return true;
  }
  ll numberOfSubstrings() {
    ll res = 0;
    for (int i = 1; i < sz; i++) res += st[i].len - st[st[i].link].len;
    return res;
  }
  void numberOfOccPreprocess() {
    vector<ii> v;
    for (int i = 1; i < sz; i++) v.push_back(make_pair(st[i].len, i));
    sort(v.begin(), v.end(), greater<ii>());
    for (int i = 0; i < sz - 1; i++) {
      int suf = st[v[i].second].link;
      st[suf].cnt += st[v[i].second].cnt;
    }
  }
  ll numberOfOcc(string &t) {
    int cur = 0;
    for (int i = 0; i < t.length(); i++) {
      cur = st[cur].next[t[i] - offset];
      if (cur == -1) return 0;
    }
    return st[cur].cnt;
  }
};
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  string a, b, c;
  cin >> a >> b >> c;
  suffixAutomaton SA(a + "@" + b + "#" + c + "$");
  int mn = min(a.size(), min(b.size(), c.size()));
  int cur = 0;
  for (int i = 1; i <= mn; i++) {
    cur += ans[i];
    if (cur >= mod) cur -= mod;
    if (cur < 0) cur += mod;
    cout << cur << ' ';
  }
  return 0;
}
