#include <bits/stdc++.h>
using namespace std;
struct suffix_array {
  static const int max_val = 32;
  static const int max_n = 300010;
  int index[max_n], rank[max_n];
  int cnt[max_n], buf1[max_n], buf2[max_n];
  int lcp[max_n];
  void build(const char* str, int n, int m = max_val) {
    int *x = buf1, *y = buf2;
    fill(cnt, cnt + m, 0);
    for (int i = 0; i < n; ++i) ++cnt[x[i] = str[i]];
    for (int i = 1; i < m; ++i) cnt[i] += cnt[i - 1];
    for (int i = n - 1; i >= 0; --i) index[--cnt[x[i]]] = i;
    for (int i = 1;; i *= 2) {
      int p = 0;
      for (int j = n - i; j < n; ++j) y[p++] = j;
      for (int j = 0; j < n; ++j)
        if (index[j] >= i) y[p++] = index[j] - i;
      fill(cnt, cnt + m, 0);
      for (int j = 0; j < n; ++j) ++cnt[x[j]];
      for (int j = 1; j < m; ++j) cnt[j] += cnt[j - 1];
      for (int j = n - 1; j >= 0; --j) index[--cnt[x[y[j]]]] = y[j];
      swap(x, y);
      p = 1;
      x[index[0]] = 0;
      for (int j = 1; j < n; ++j)
        x[index[j]] = is_equal(y, index[j - 1], index[j], i) ? p - 1 : p++;
      if (p == n) break;
      m = p;
    }
    copy(x, x + n, rank);
  }
  bool is_equal(int* r, int a, int b, int l) {
    return r[a] == r[b] && r[a + l] == r[b + l];
  }
  void compute_lcp(const char* str, int n) {
    lcp[0] = 0;
    int l = 0;
    for (int i = 0; i < n; ++i) {
      if (rank[i] == 0) continue;
      int p = index[rank[i] - 1];
      for (l = (l == 0 ? 0 : l - 1); str[i + l] == str[p + l]; ++l)
        ;
      lcp[rank[i]] = l;
    }
  }
};
long long cur_cnt;
suffix_array sa;
char str[300010];
int n, id1, id2, id3, len1, len2, len3;
long long ans[300010];
struct disjoint_set {
  int p[300010], cnt[300010][3];
  void clear(int n) {
    for (int i = 0; i < n; ++i) {
      p[i] = i;
      cnt[i][0] = cnt[i][1] = cnt[i][2] = 0;
      if (sa.index[i] != id1 && sa.index[i] != id2) {
        if (sa.index[i] < id1)
          ++cnt[i][0];
        else if (sa.index[i] < id2)
          ++cnt[i][1];
        else
          ++cnt[i][2];
      }
    }
    cur_cnt = 0;
  }
  int get_root(int k) {
    if (p[k] == k) {
      return k;
    } else {
      int tmp = get_root(p[k]);
      p[k] = tmp;
      for (int i = 0; i < 3; ++i) {
        cnt[tmp][i] += cnt[k][i];
        cnt[k][i] = 0;
      }
      return tmp;
    }
  }
  bool merge(int a, int b) {
    int r1 = get_root(a), r2 = get_root(b);
    if (r1 == r2) return false;
    cur_cnt -= (long long)cnt[r1][0] * cnt[r1][1] * cnt[r1][2];
    cur_cnt -= (long long)cnt[r2][0] * cnt[r2][1] * cnt[r2][2];
    p[r2] = r1;
    get_root(r2);
    cur_cnt += (long long)cnt[r1][0] * cnt[r1][1] * cnt[r1][2];
    return true;
  }
};
disjoint_set ds;
bool solve() {
  if (scanf("%s", str) == EOF) return false;
  id1 = strlen(str);
  str[id1] = 'z' + 1;
  scanf("%s", str + id1 + 1);
  id2 = strlen(str);
  str[id2] = 'z' + 2;
  scanf("%s", str + id2 + 1);
  id3 = strlen(str);
  str[id3] = 'z' + 3;
  for (int i = 0; i <= id3; ++i) str[i] -= 'a';
  sa.build(str, id3 + 1);
  sa.compute_lcp(str, id3 + 1);
  vector<pair<int, int> > vec;
  for (int i = 1; i < id3; ++i) {
    vec.push_back(make_pair(sa.lcp[i], i));
  }
  sort(vec.begin(), vec.end());
  int max_l = min(min(id1, id2 - id1 - 1), id3 - id2 - 1);
  int L = max_l;
  int last = id3;
  ds.clear(id3);
  while (!vec.empty()) {
    int cur = vec.back().first;
    while (max_l > cur) {
      ans[max_l] = cur_cnt;
      --max_l;
    }
    while (!vec.empty() && vec.back().first == cur) {
      ds.merge(vec.back().second - 1, vec.back().second);
      vec.pop_back();
    }
    last = cur;
  }
  for (int i = 1; i <= L; ++i) {
    cout << ans[i] % 1000000007;
    if (i == L)
      cout << endl;
    else
      cout << ' ';
  }
  return true;
}
int main() {
  while (solve())
    ;
  return 0;
}
