#include <bits/stdc++.h>
#pragma warning(disable : 4244 4267 4018 4996 4800)
#pragma comment(linker, "/stack:10000000")
using namespace std;
istream& in = cin;
ostream& out = cout;
string str[3];
long long mod = 1000000007;
struct counter {
  counter(size_t n) {
    size_t ofs = 1;
    for (; ofs < n; ofs <<= 1)
      ;
    tree.resize(ofs << 1);
  }
  void add(size_t lo, size_t hi, long long num) {
    size_t const ofs = tree.size() / 2;
    lo += ofs;
    hi += ofs;
    while (lo > 0 && lo <= hi) {
      if ((lo & 1) == 1) tree[lo] = (tree[lo] + num) % mod;
      if ((hi & 1) == 0) tree[hi] = (tree[hi] + num) % mod;
      hi--;
      hi >>= 1;
      lo++;
      lo >>= 1;
    }
  }
  long long get(size_t idx) {
    long long res = 0;
    for (size_t i = tree.size() / 2 + idx; i > 0; i >>= 1)
      res = (res + tree[i]) % mod;
    return res;
  }
  vector<long long> tree;
};
struct suffix_tree {
  suffix_tree(string const& str, counter& cnt) : s(str), cnt(cnt) {
    int n = 0, pos = 0;
    nodes.push_back(node());
    for (int i = 0; i < s.size() - 1; ++i) {
      int curpos = pos, prevn = n;
      if (n) {
        curpos -= nodes[n].size();
        n = nodes[n].parent;
        if (n)
          n = nodes[n].suffix;
        else
          curpos++;
      } else
        curpos = pos = i;
      while (curpos < pos) {
        int prev;
        n = find_child(n, s[curpos], prev);
        if (curpos + nodes[n].size() > pos) {
          n = split(n, pos - curpos, prev);
          break;
        }
        curpos += nodes[n].size();
      }
      if (prevn) nodes[prevn].suffix = n;
      for (;;) {
        int prev;
        int e = find_child(n, s[pos], prev);
        if (e == -1) break;
        for (int i = nodes[e].l; i < nodes[e].r; ++i, ++pos) {
          if (s[i] != s[pos]) {
            n = split(e, i - nodes[e].l, prev);
            goto finish;
          }
        }
        n = e;
      }
    finish:
      nodes.push_back(node(pos, s.size(), n, nodes[n].child));
      nodes[n].child = nodes.size() - 1;
    }
  }
  int find_child(int n, char ch, int& prev) {
    int t = nodes[n].child;
    prev = -1;
    while (t != -1) {
      if (s[nodes[t].l] == ch) return t;
      prev = t;
      t = nodes[t].sibling;
    }
    return -1;
  }
  int split(int n, int len, int prev) {
    int m = nodes.size();
    nodes.push_back(node(nodes[n].l, nodes[n].l + len, nodes[n].parent,
                         nodes[n].sibling, n));
    if (prev == -1)
      nodes[nodes[n].parent].child = m;
    else
      nodes[prev].sibling = m;
    nodes[n].l = nodes[n].l + len;
    nodes[n].parent = m;
    nodes[n].sibling = -1;
    return m;
  }
  struct node {
    node(int l = -1, int r = -1, int parent = -1, int sibling = -1,
         int child = -1)
        : l(l),
          r(r),
          parent(parent),
          suffix(-1),
          child(child),
          sibling(sibling) {
      cnt[0] = cnt[1] = cnt[2] = 0;
    }
    int size() const { return r - l; }
    int l, r, parent, suffix, child, sibling;
    long long cnt[3];
  };
  void mark(int n, int len) {
    int pos = 0;
    for (int i = 0; i < 3; ++i) {
      pos += str[i].size() + 1;
      if (contains(n, pos - 1)) {
        ++nodes[n].cnt[i];
        return;
      }
    }
    for (int t = nodes[n].child; t != -1; t = nodes[t].sibling) {
      mark(t, len + nodes[n].r - nodes[n].l);
      for (int i = 0; i < 3; ++i) nodes[n].cnt[i] += nodes[t].cnt[i];
    }
    long long val = nodes[n].cnt[0] * nodes[n].cnt[1] * nodes[n].cnt[2] % mod;
    if (val && n) {
      int l = len;
      int r = l + nodes[n].r - nodes[n].l - 1;
      cnt.add(l, r, val);
    }
  }
  bool contains(int n, int pos) {
    return nodes[n].l <= pos && pos < nodes[n].r;
  }
  string s;
  vector<node> nodes;
  counter& cnt;
};
int main() {
  in >> str[0] >> str[1] >> str[2];
  int size = min(str[0].size(), min(str[1].size(), str[2].size()));
  counter cnt(size);
  suffix_tree t(str[0] + char(0) + str[1] + char(1) + str[2] + char(2), cnt);
  t.mark(0, 0);
  for (int i = 0; i < size; ++i) out << cnt.get(i) << ' ';
  return 0;
}
