#include <bits/stdc++.h>
using namespace std;
struct Node {
  int l, r, p, link;
  map<char, int> nxt;
  Node(int l = 0, int r = 0, int p = -1, int link = -1)
      : l(l), r(r), p(p), link(link) {}
  int& operator[](char c) {
    if (!nxt.count(c)) nxt[c] = -1;
    return nxt[c];
  }
};
const int maxn = 1000 * 1000 + 15;
const int mod = 1e9 + 7;
int n;
char s[maxn];
string ss[3];
Node node[maxn];
int size;
inline int len(int v) { return node[v].r - node[v].l; }
int addVertex(int p, int l, int r) {
  node[size] = Node(l, r, p, -1);
  node[p][s[l]] = size;
  return size++;
}
int Split(pair<int, int> ptr) {
  int v = ptr.first;
  int up = ptr.second;
  int down = len(v) - up;
  if (up == 0) return v;
  if (down == 0) return node[v].p;
  int mid = addVertex(node[v].p, node[v].l, node[v].l + down);
  node[v].l += down;
  node[v].p = mid;
  node[mid][s[node[v].l]] = v;
  return mid;
}
pair<int, int> Down(int v, int l, int r) {
  if (l == r) return make_pair(v, 0);
  for (;;) {
    v = node[v][s[l]];
    if (len(v) >= r - l) {
      return make_pair(v, len(v) - (r - l));
    }
    l += len(v);
  }
  throw;
}
int link(int v) {
  if (node[v].link == -1) {
    node[v].link =
        Split(Down(link(node[v].p), node[v].l + (node[v].p == 0), node[v].r));
  }
  return node[v].link;
}
pair<int, int> Go(pair<int, int> ptr, char c) {
  int v = ptr.first, up = ptr.second;
  if (up != 0)
    return s[node[v].r - up] == c ? make_pair(v, up - 1) : make_pair(-1, -1);
  v = node[v][c];
  return v == -1 ? make_pair(-1, -1) : make_pair(v, len(v) - 1);
}
pair<int, int> AddChar(pair<int, int> ptr, int pos) {
  while (true) {
    pair<int, int> nptr = Go(ptr, s[pos]);
    if (nptr.first != -1) return nptr;
    int v = Split(ptr);
    addVertex(v, pos, n);
    if (v == 0) return make_pair(0, 0);
    ptr = make_pair(link(v), 0);
  }
  throw;
}
void MakeTree() {
  size = 0;
  node[size++] = Node(0, 0, -1, 0);
  pair<int, int> ptr = make_pair(0, 0);
  for (int _n(n), i(0); i < _n; i++) ptr = AddChar(ptr, i);
}
char buf[maxn];
int numstr[maxn];
inline bool read() {
  for (int _n(3), i(0); i < _n; i++) {
    assert(scanf("%s", buf) == 1);
    ss[i] = string(buf);
    for (int _n(int(ss[i].size())), j(0); j < _n; j++) {
      numstr[n] = i;
      s[n++] = ss[i][j];
    }
    numstr[n] = i;
    s[n++] = char('0' + i);
  }
  return true;
}
int ans[maxn];
int cnt[maxn][3];
inline int mult(int a, int b) {
  long long c = 1ll * a * b;
  if (c >= mod) c %= mod;
  return int(c);
}
inline int add(int a, int b) {
  a += b;
  while (a < 0) a += mod;
  while (a >= mod) a -= mod;
  return a;
}
inline void upd(int lf, int rg, int val) {
  ans[lf] = add(ans[lf], val);
  ans[rg + 1] = add(ans[rg + 1], -val);
}
void dfs(int v, int len) {
  len += ::len(v);
  if (node[v].nxt.empty()) {
    cnt[v][numstr[n - len]]++;
    return;
  }
  for (auto it : node[v].nxt) {
    dfs(it.second, len);
    for (int _n(3), i(0); i < _n; i++) cnt[v][i] += cnt[it.second][i];
  }
  int cur = 1;
  for (int _n(3), i(0); i < _n; i++) cur = mult(cur, cnt[v][i]);
  upd(len - ::len(v) + 1, len, cur);
}
inline void solve() {
  MakeTree();
  dfs(0, 0);
  int minv = 1011111111;
  for (int _n(3), i(0); i < _n; i++) minv = min(minv, int(ss[i].size()));
  for (int _n(minv + 1), i(1); i < _n; i++) {
    ans[i] = add(ans[i], ans[i - 1]);
    printf("%d ", ans[i]);
  }
  puts("");
}
int main() {
  assert(read());
  solve();
  return 0;
}
