#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <memory.h>
#include <algorithm>
#include <cassert>

using namespace std;

string s;

const int maxn = 1e5 * 3 + 15;

class suffixVert{
public:
	int l, r, suff, par, depth;
	int g[35];
    int d[35];
	inline int len() {
		return r - l;
	}
	suffixVert() {suff = -1, par = -1, l = 0, r = 0; memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));}
	suffixVert(int _l, int _r, int _par) {suff = -1, l = _l, r = _r, par = _par; memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));}
};

suffixVert * z;
int sz, real_size;

void shrink() {
//    double coeff = real_size > 1e5 ? 1.2 : 2;
    double coeff = 1.1;
    z = (suffixVert *) realloc(z, sizeof(suffixVert) * int(coeff * real_size));
//    for (int i = real_size; i < int(coeff * real_size); ++i)
//        z[i] = suffixVert();
    real_size = int(real_size * coeff);
}

inline int next(int v, char c)
{
	return z[v].g[(int)c];
}

class state{
public:
	int v, pos;
	state() {v = 0, pos = 0;}
	state(int _v, int _pos) { v = _v, pos = _pos;}
};

state pos;

state findState(state st, int l, int r)
{
	while (l < r)
	{
//        assert(st.v >= 0 && st.v <= sz);
//        assert(l >= 0 && l < s.size());
//        assert(r >= 0 && r <= s.size());
		if (st.pos == z[st.v].len())
		{
			st.pos = 0;
			st.v = next(st.v, s[l]);
			if (st.v == -1)
            return st;
		} else {
			if (s[z[st.v].l + st.pos] != s[l])
				return state(-1, -1);
			if (r - l < z[st.v].len() - st.pos)
				return state(st.v, st.pos + r - l);
			l += z[st.v].len() - st.pos;
			st.pos = z[st.v].len();
		}
	}
	return st;
}

int cut_edge(state p)
{
//    cerr << p.v << endl;
//    assert(p.v >= 0 && p.v <= sz);
	if (p.pos == z[p.v].len())
		return p.v;
	if (p.pos == 0)
		return z[p.v].par;
	suffixVert tek = z[p.v];
	int last = sz++;
    if (last >= real_size) shrink();
//    assert(last >= 0 && last <= sz);
	z[last] = suffixVert(tek.l, tek.l + p.pos, tek.par);
//    assert(tek.l + p.pos >= 0 && tek.l + p.pos < s.size());
	z[last].g[(int)s[tek.l + p.pos]] = p.v;
//    assert(tek.par >= 0 && tek.par <= sz);
	z[tek.par].g[(int)s[tek.l]] = last;
//    assert(p.v >= 0 && p.v <= sz);
	z[p.v].par = last;
	z[p.v].l += p.pos;
	return last;
}

int make_link(int v)
{
  //  assert(v >= 0 && v <= sz);
	if (z[v].suff != -1)
		return z[v].suff;
	if (z[v].par == -1)
		return 0;
	int suff_par = make_link(z[v].par);
//    assert(suff_par >= 0 && suff_par <= sz);
//    assert(v >= 0 && v <= sz);
	state tek = findState(state(suff_par, z[suff_par].len()), z[v].l + (z[v].par == 0), z[v].r);
//    cerr << "v == " << v << endl;
    int tmp = cut_edge(tek);
//    cerr << "omg: " << tmp << endl;
	z[v].suff = tmp; // HERE PROBLEM
//    cerr << z[v].suff << endl;
	return z[v].suff;
}

void new_vert(int i)
{
	while(1)
	{
		state npos = findState(pos, i, i + 1);
		if (npos.v != -1)
		{
			pos = npos;
			return;
		}
		int p = cut_edge(pos);
		int last = sz++;
//        cerr << "last: " << last << endl;
        if (last >= real_size) shrink();
//        cerr << "last: " << last << " " << real_size << endl;
		z[last] = suffixVert(i, s.size(), p);
 //       cerr << "p: " << p << endl;
		z[p].g[(int)s[i]] = last;
//        cerr << "p2: " << p << endl;

		pos.v = make_link(p);
        if (pos.v == -1) pos.v = 0;
		pos.pos = z[pos.v].len();
		if (!p)
			break;
	}
}

int it = 0;

int l[maxn];

void calc_depth(int v, int cur) {
    cur += z[v].len();
    z[v].depth = cur;

    for (char c = 0; c <= 34; ++c) {
    	if (z[v].g[(int)c] != -1) {
    		calc_depth(z[v].g[(int)c], cur);
            for (int i = z[z[v].g[(int)c]].l; i < z[z[v].g[(int)c]].r; ++i)
                z[v].d[(int)s[i]] += 1;
//            z[v].d[(int)c] += 1;
            for (char c2 = 0; c2 <= 34; ++c2) {
                z[v].d[(int)c2] += z[z[v].g[(int)c]].d[(int)c2];
            }
        }
    }
}

void dfs(int v, int cur) {
    for (int i = z[v].l; i < z[v].r; ++i) {
//        if (z[v].d[0] <= 2 || z[v].d[1] <= 1 || z[v].d[2] == 0)
//            continue;
//        cerr << v << char(s[i] - 4 + 'a') << " " << cur + i - z[v].l + 1 << " " << z[v].d[0] << " " << z[v].d[1] << " " << z[v].d[2] << endl;
        long long tmp = (z[v].d[0] - z[v].d[1]);
        long long tmp2 = (z[v].d[1] - z[v].d[2]);
        long long tmp3 = z[v].d[2];
//        cerr << cur + i - z[v].l << " " << tmp << " " << tmp2 << " " << tmp3 << endl;
        if (tmp > 0 && tmp2 > 0 && tmp3 > 0) {
            l[cur + i - z[v].l] += tmp * tmp2 * tmp3;
        }
//       l[cur + i - z[v].l + 1] += (z[v].d[0] - z[v].d[1] - z) * (z[v].d[1] - 1) * (z[v].d[2] - 0);
    }
    cur += z[v].len();

    for (char c = 0; c <= 34; ++c)
        if (z[v].g[(int)c] != -1)
            dfs(z[v].g[(int)(c)], cur);
}

int main()
{
    ios_base::sync_with_stdio(0);
    string s1, s2, s3;
    cin >> s1 >> s2 >> s3;

    int st_size = 600000;

    real_size = st_size;
    z = (suffixVert *) malloc(sizeof(suffixVert) * real_size);
//    cerr << z << endl;
//    for (int i = 0; i < real_size; ++i)
//        z[i] = suffixVert();
    z[0] = suffixVert();

    for (int i = 0; i < s1.size(); ++i)
        s1[i] = s1[i] - 'a' + 4;
    for (int i = 0; i < s2.size(); ++i)
        s2[i] = s2[i] - 'a' + 4;
    for (int i = 0; i < s3.size(); ++i)
        s3[i] = s3[i] - 'a' + 4;

    s = s1;
    s.push_back(2);
    s += s2;
    s.push_back(1);
    s += s3;
    s.push_back(0);

	sz = 1;

	for (int i = 0; i < s.size(); ++i) {
//        cerr << i << " " << int(s[0]) << " " << sz << endl;
		new_vert(i);
//        cerr << i << endl;
    }
//    cerr << "size = " << sz << endl;
    calc_depth(0, 0);

//    for (int i = 0; i <= 34; ++i)
//        cerr << "i == " << z[0].d[i] << endl;

    dfs(0, 0);

    for (int i = 0; i < min(s1.size(), min(s2.size(), s3.size())); ++i)
        cout << l[i] << " ";

	return 0;
}


#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <memory.h>
#include <algorithm>
#include <cassert>
#include <set>

using namespace std;

string s;

const int maxn = 2 * 1e6;

const int md = 1e9 + 7;

class suffixVert{
public:
	int l, r, suff, par, depth;
//	int g[30];
//    int d[30];
    map<int, int> g;
    map<int, int> d;
	inline int len() {
		return r - l;
	}
	suffixVert() {suff = -1, par = -1, l = 0, r = 0;/* memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));*/}
	suffixVert(int _l, int _r, int _par) {suff = -1, l = _l, r = _r, par = _par;/*memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));*/}
};

suffixVert z[maxn];
int sz, real_size;
int dyn[maxn][3];

void shrink() {
/*    cerr << "Here" << endl;
    exit(1);
//    double coeff = real_size > 1e5 ? 1.2 : 2;
    double coeff = 2;
    z = (suffixVert *) realloc(z, sizeof(suffixVert) * int(coeff * real_size));
//    for (int i = real_size; i < int(coeff * real_size); ++i)
//        z[i] = suffixVert();
    real_size = int(real_size * coeff);*/
}

inline int next(int v, char c)
{
    if (z[v].g.find((int)c) == z[v].g.end())
        return -1;
	return z[v].g[(int)c];
}

class state{
public:
	int v, pos;
	state() {v = 0, pos = 0;}
	state(int _v, int _pos) { v = _v, pos = _pos;}
};

state pos;

state findState(state st, int l, int r)
{
	while (l < r)
	{
//        assert(st.v >= 0 && st.v <= sz);
//        assert(l >= 0 && l < s.size());
//        assert(r >= 0 && r <= s.size());
		if (st.pos == z[st.v].len())
		{
			st.pos = 0;
			st.v = next(st.v, s[l]);
			if (st.v == -1)
            return st;
		} else {
			if (s[z[st.v].l + st.pos] != s[l])
				return state(-1, -1);
			if (r - l < z[st.v].len() - st.pos)
				return state(st.v, st.pos + r - l);
			l += z[st.v].len() - st.pos;
			st.pos = z[st.v].len();
		}
	}
	return st;
}

int cut_edge(state p)
{
//    cerr << p.v << endl;
//    assert(p.v >= 0 && p.v <= sz);
	if (p.pos == z[p.v].len())
		return p.v;
	if (p.pos == 0)
		return z[p.v].par;
	suffixVert tek = z[p.v];
	int last = sz++;
    if (last >= real_size) shrink();
//    assert(last >= 0 && last <= sz);
	z[last] = suffixVert(tek.l, tek.l + p.pos, tek.par);
//    assert(tek.l + p.pos >= 0 && tek.l + p.pos < s.size());
	z[last].g[(int)s[tek.l + p.pos]] = p.v;
//    assert(tek.par >= 0 && tek.par <= sz);
	z[tek.par].g[(int)s[tek.l]] = last;
//    assert(p.v >= 0 && p.v <= sz);
	z[p.v].par = last;
	z[p.v].l += p.pos;
	return last;
}

int make_link(int v)
{
  //  assert(v >= 0 && v <= sz);
	if (z[v].suff != -1)
		return z[v].suff;
	if (z[v].par == -1)
		return 0;
	int suff_par = make_link(z[v].par);
//    assert(suff_par >= 0 && suff_par <= sz);
//    assert(v >= 0 && v <= sz);
	state tek = findState(state(suff_par, z[suff_par].len()), z[v].l + (z[v].par == 0), z[v].r);
//    cerr << "v == " << v << endl;
    int tmp = cut_edge(tek);
//    cerr << "omg: " << tmp << endl;
	z[v].suff = tmp; // HERE PROBLEM
//    cerr << z[v].suff << endl;
	return z[v].suff;
}

void new_vert(int i)
{
	while(1)
	{
		state npos = findState(pos, i, i + 1);
		if (npos.v != -1)
		{
			pos = npos;
			return;
		}
		int p = cut_edge(pos);
		int last = sz++;
//        cerr << "last: " << last << endl;
        if (last >= real_size) shrink();
//        cerr << "last: " << last << " " << real_size << endl;
		z[last] = suffixVert(i, s.size(), p);
 //       cerr << "p: " << p << endl;
		z[p].g[(int)s[i]] = last;
//        cerr << "p2: " << p << endl;

		pos.v = make_link(p);
        if (pos.v == -1) pos.v = 0;
		pos.pos = z[pos.v].len();
		if (!p)
			break;
	}
}

int it = 0;

int l[maxn];

int calc_d(int l, int r, int c) {
    if (l == 0)
        return dyn[r - 1][c];
//    cerr << l << " " << r << " " << c << " " << dyn[r - 1][c] - dyn[l - 1][c] << endl;
    return dyn[r - 1][c] - dyn[l - 1][c];
}

void calc_depth(int v, int cur) {
    cur += z[v].len();
    z[v].depth = cur;

    for (map<int, int>::const_iterator it = z[v].g.begin(); it != z[v].g.end(); ++it) {
//    for (char c = 0; c <= 29; ++c) {
//    	if (next(v, c) != -1) {
//            int to = next(v, c);
            int to = it->second;
            char c = it->first;
    		calc_depth(to, cur);
/*            int tmp[3];
            tmp[0] = tmp[1] = tmp[2] = 0;
            for (int i = z[to].l; i < z[to].r; ++i)
                if ((int)s[i] <= 2)
                    tmp[s[i]] += 1;*/
            z[v].d[0] += calc_d(z[to].l, z[to].r, 0);
            z[v].d[1] += calc_d(z[to].l, z[to].r, 1);
            z[v].d[2] += calc_d(z[to].l, z[to].r, 2);
//            cerr << calc_d(z[to].l, z[to].r, 2) << " " << tmp[2] << endl;
            z[v].d[0] += z[to].d[0];
            z[v].d[1] += z[to].d[1];
            z[v].d[2] += z[to].d[2];
//            z[v].d[(int)c] += 1;
//            for (char c2 = 0; c2 <= 29; ++c2) {
//                z[v].d[(int)c2] += z[z[v].g[(int)c]].d[(int)c2];
//            }
        }
//    }
}

class node{
public:
    int l, r;
    long long value;
    node() {}
};

bool cmp(node a, node b) {
    if (a.l == b.l)
        return a.r < b.r;
    return a.l < b.l;
}

vector<node> ans;

void dfs(int v, int cur) {
//    for (int i = z[v].l; i < z[v].r; ++i) {
//        if (z[v].d[0] <= 2 || z[v].d[1] <= 1 || z[v].d[2] == 0)
//            continue;
//        cerr << v << char(s[i] - 4 + 'a') << " " << cur + i - z[v].l + 1 << " " << z[v].d[0] << " " << z[v].d[1] << " " << z[v].d[2] << endl;
        long long tmp1 = (z[v].d[0] - z[v].d[1]);
        long long tmp2 = (z[v].d[1] - z[v].d[2]);
        long long tmp3 = z[v].d[2];
//        cerr << cur + i - z[v].l << " " << tmp << " " << tmp2 << " " << tmp3 << endl;
        if (tmp1 > 0 && tmp2 > 0 && tmp3 > 0 && z[v].len() > 0) {
            node tmp;
            tmp.l = cur;
            tmp.r = cur + z[v].len();
            tmp.value = (tmp1 * 1ll * tmp2 * 1ll * tmp3) % md;
            ans.push_back(tmp);
//            l[cur + i - z[v].l] = (l[cur + i - z[v].l] + tmp * 1ll * tmp2 * 1ll * tmp3) % md;
        }
//       l[cur + i - z[v].l + 1] += (z[v].d[0] - z[v].d[1] - z) * (z[v].d[1] - 1) * (z[v].d[2] - 0);
//    }
    cur += z[v].len();

//    for (char c = 0; c <= 29; ++c)
    for (map<int, int>::const_iterator it = z[v].g.begin(); it != z[v].g.end(); ++it)
//        if (next(v, c) != -1)
//            dfs(next(v, c), cur);
        dfs(it->second, cur);
}

string s1, s2, s3;
int main()
{
    ios_base::sync_with_stdio(0);
    cin >> s1 >> s2 >> s3;

    int st_size = maxn;

    real_size = st_size;
//    z = (suffixVert *) malloc(sizeof(suffixVert) * real_size);
//    cerr << z << endl;
//    for (int i = 0; i < real_size; ++i)
//        z[i] = suffixVert();
    z[0] = suffixVert();

    for (int i = 0; i < s1.size(); ++i)
        s1[i] = s1[i] - 'a' + 3;
    for (int i = 0; i < s2.size(); ++i)
        s2[i] = s2[i] - 'a' + 3;
    for (int i = 0; i < s3.size(); ++i)
        s3[i] = s3[i] - 'a' + 3;

    s = s1;
    s.push_back(2);
    s += s2;
    s.push_back(1);
    s += s3;
    s.push_back(0);

    if (s[0] <= 2)
        dyn[0][s[0]] = 1;
    for (int i = 1; i < s.size(); ++i) {
        for (int j = 0; j <= 2; ++j)
            dyn[i][j] = dyn[i - 1][j];
        if (s[i] <= 2)
            dyn[i][s[i]]++;
    }
/*    for (int i = 0; i < s.size(); ++i)
        cerr << (int)s[i] << " ";
    cerr << endl;
    for (int i = 0; i < s.size(); ++i)
        cerr << dyn[i][0] << " " << dyn[i][1] << " " << dyn[i][2] << endl;*/

	sz = 1;

    cerr << s.size() << endl;

	for (int i = 0; i < s.size(); ++i) {
//        cerr << i << " " << int(s[0]) << " " << sz << endl;
		new_vert(i);
//        cerr << i << endl;
    }
    cerr << sz << endl;
    calc_depth(0, 0);

//    for (int i = 0; i <= 34; ++i)
//        cerr << "i == " << z[0].d[i] << endl;

    cerr << "size = " << sz << endl;
    dfs(0, 0);

    sort(ans.begin(), ans.end(), cmp);

//    for (int i = 0; i < ans.size(); ++i)
//        cerr << ans[i].l << " " << ans[i].r << " " << ans[i].value << endl;

    long long cur = 0;
    int p = 0;
    set<pair<int, long long> > z_s;
    for (int i = 0; i < min(s1.size(), min(s2.size(), s3.size())); ++i) {
        while (z_s.size() > 0 && z_s.begin()->first <= i) {
            cur -= z_s.begin()->second;
            z_s.erase(z_s.begin());
        }
        while (p < ans.size() && ans[p].l <= i) {
            cur += ans[p].value;
            z_s.insert(make_pair(ans[p].r, ans[p].value));
            ++p;
        }
        cout << cur % md << " ";
    }

//    for (int i = 0; i < min(s1.size(), min(s2.size(), s3.size())); ++i)
//        cout << l[i] << " ";

	return 0;
}


#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <memory.h>
#include <algorithm>
#include <cassert>

using namespace std;

string s;

const int maxn = 2 * 1e6;

class suffixVert{
public:
	int l, r, suff, par, depth;
//	int g[30];
//    int d[30];
    map<int, int> g;
    map<int, int> d;
	inline int len() {
		return r - l;
	}
	suffixVert() {suff = -1, par = -1, l = 0, r = 0;/* memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));*/}
	suffixVert(int _l, int _r, int _par) {suff = -1, l = _l, r = _r, par = _par;/*memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));*/}
};

suffixVert z[maxn];
int sz, real_size;

void shrink() {
/*    cerr << "Here" << endl;
    exit(1);
//    double coeff = real_size > 1e5 ? 1.2 : 2;
    double coeff = 2;
    z = (suffixVert *) realloc(z, sizeof(suffixVert) * int(coeff * real_size));
//    for (int i = real_size; i < int(coeff * real_size); ++i)
//        z[i] = suffixVert();
    real_size = int(real_size * coeff);*/
}

inline int next(int v, char c)
{
    if (z[v].g.find((int)c) == z[v].g.end())
        return -1;
	return z[v].g[(int)c];
}

class state{
public:
	int v, pos;
	state() {v = 0, pos = 0;}
	state(int _v, int _pos) { v = _v, pos = _pos;}
};

state pos;

state findState(state st, int l, int r)
{
	while (l < r)
	{
//        assert(st.v >= 0 && st.v <= sz);
//        assert(l >= 0 && l < s.size());
//        assert(r >= 0 && r <= s.size());
		if (st.pos == z[st.v].len())
		{
			st.pos = 0;
			st.v = next(st.v, s[l]);
			if (st.v == -1)
            return st;
		} else {
			if (s[z[st.v].l + st.pos] != s[l])
				return state(-1, -1);
			if (r - l < z[st.v].len() - st.pos)
				return state(st.v, st.pos + r - l);
			l += z[st.v].len() - st.pos;
			st.pos = z[st.v].len();
		}
	}
	return st;
}

int cut_edge(state p)
{
//    cerr << p.v << endl;
//    assert(p.v >= 0 && p.v <= sz);
	if (p.pos == z[p.v].len())
		return p.v;
	if (p.pos == 0)
		return z[p.v].par;
	suffixVert tek = z[p.v];
	int last = sz++;
    if (last >= real_size) shrink();
//    assert(last >= 0 && last <= sz);
	z[last] = suffixVert(tek.l, tek.l + p.pos, tek.par);
//    assert(tek.l + p.pos >= 0 && tek.l + p.pos < s.size());
	z[last].g[(int)s[tek.l + p.pos]] = p.v;
//    assert(tek.par >= 0 && tek.par <= sz);
	z[tek.par].g[(int)s[tek.l]] = last;
//    assert(p.v >= 0 && p.v <= sz);
	z[p.v].par = last;
	z[p.v].l += p.pos;
	return last;
}

int make_link(int v)
{
  //  assert(v >= 0 && v <= sz);
	if (z[v].suff != -1)
		return z[v].suff;
	if (z[v].par == -1)
		return 0;
	int suff_par = make_link(z[v].par);
//    assert(suff_par >= 0 && suff_par <= sz);
//    assert(v >= 0 && v <= sz);
	state tek = findState(state(suff_par, z[suff_par].len()), z[v].l + (z[v].par == 0), z[v].r);
//    cerr << "v == " << v << endl;
    int tmp = cut_edge(tek);
//    cerr << "omg: " << tmp << endl;
	z[v].suff = tmp; // HERE PROBLEM
//    cerr << z[v].suff << endl;
	return z[v].suff;
}

void new_vert(int i)
{
	while(1)
	{
		state npos = findState(pos, i, i + 1);
		if (npos.v != -1)
		{
			pos = npos;
			return;
		}
		int p = cut_edge(pos);
		int last = sz++;
//        cerr << "last: " << last << endl;
        if (last >= real_size) shrink();
//        cerr << "last: " << last << " " << real_size << endl;
		z[last] = suffixVert(i, s.size(), p);
 //       cerr << "p: " << p << endl;
		z[p].g[(int)s[i]] = last;
//        cerr << "p2: " << p << endl;

		pos.v = make_link(p);
        if (pos.v == -1) pos.v = 0;
		pos.pos = z[pos.v].len();
		if (!p)
			break;
	}
}

int it = 0;

int l[maxn];

void calc_depth(int v, int cur) {
    cur += z[v].len();
    z[v].depth = cur;

    for (map<int, int>::const_iterator it = z[v].g.begin(); it != z[v].g.end(); ++it) {
//    for (char c = 0; c <= 29; ++c) {
//    	if (next(v, c) != -1) {
//            int to = next(v, c);
            int to = it->second;
            char c = it->first;
    		calc_depth(to, cur);
            for (int i = z[to].l; i < z[to].r; ++i)
                z[v].d[(int)s[i]] += 1;
            z[v].d[0] += z[to].d[0];
            z[v].d[1] += z[to].d[1];
            z[v].d[2] += z[to].d[2];
//            z[v].d[(int)c] += 1;
//            for (char c2 = 0; c2 <= 29; ++c2) {
//                z[v].d[(int)c2] += z[z[v].g[(int)c]].d[(int)c2];
//            }
        }
//    }
}

void dfs(int v, int cur) {
    for (int i = z[v].l; i < z[v].r; ++i) {
//        if (z[v].d[0] <= 2 || z[v].d[1] <= 1 || z[v].d[2] == 0)
//            continue;
//        cerr << v << char(s[i] - 4 + 'a') << " " << cur + i - z[v].l + 1 << " " << z[v].d[0] << " " << z[v].d[1] << " " << z[v].d[2] << endl;
        long long tmp = (z[v].d[0] - z[v].d[1]);
        long long tmp2 = (z[v].d[1] - z[v].d[2]);
        long long tmp3 = z[v].d[2];
//        cerr << cur + i - z[v].l << " " << tmp << " " << tmp2 << " " << tmp3 << endl;
        if (tmp > 0 && tmp2 > 0 && tmp3 > 0) {
            l[cur + i - z[v].l] += tmp * tmp2 * tmp3;
        }
//       l[cur + i - z[v].l + 1] += (z[v].d[0] - z[v].d[1] - z) * (z[v].d[1] - 1) * (z[v].d[2] - 0);
    }
    cur += z[v].len();

//    for (char c = 0; c <= 29; ++c)
    for (map<int, int>::const_iterator it = z[v].g.begin(); it != z[v].g.end(); ++it)
//        if (next(v, c) != -1)
//            dfs(next(v, c), cur);
        dfs(it->second, cur);
}

string s1, s2, s3;
int main()
{
    ios_base::sync_with_stdio(0);
    cin >> s1 >> s2 >> s3;

    int st_size = maxn;

    real_size = st_size;
//    z = (suffixVert *) malloc(sizeof(suffixVert) * real_size);
//    cerr << z << endl;
//    for (int i = 0; i < real_size; ++i)
//        z[i] = suffixVert();
    z[0] = suffixVert();

    for (int i = 0; i < s1.size(); ++i)
        s1[i] = s1[i] - 'a' + 3;
    for (int i = 0; i < s2.size(); ++i)
        s2[i] = s2[i] - 'a' + 3;
    for (int i = 0; i < s3.size(); ++i)
        s3[i] = s3[i] - 'a' + 3;

    s = s1;
    s.push_back(2);
    s += s2;
    s.push_back(1);
    s += s3;
    s.push_back(0);

	sz = 1;

    cerr << s.size() << endl;

	for (int i = 0; i < s.size(); ++i) {
//        cerr << i << " " << int(s[0]) << " " << sz << endl;
		new_vert(i);
//        cerr << i << endl;
    }
    calc_depth(0, 0);

//    for (int i = 0; i <= 34; ++i)
//        cerr << "i == " << z[0].d[i] << endl;

    cerr << "size = " << sz << endl;
    dfs(0, 0);

    for (int i = 0; i < min(s1.size(), min(s2.size(), s3.size())); ++i)
        cout << l[i] << " ";

	return 0;
}


#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <memory.h>
#include <algorithm>
#include <cassert>

using namespace std;

string s;

const int maxn = 1e2 * 3 + 15;

class suffixVert{
public:
	int l, r, suff, par, depth;
	int g[33];
    int d[33];
	inline int len() {
		return r - l;
	}
	suffixVert() {suff = -1, par = -1, l = 0, r = 0; memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));}
	suffixVert(int _l, int _r, int _par) {suff = -1, l = _l, r = _r, par = _par; memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));}
};

suffixVert z[maxn];
int sz, real_size;

void shrink() {
/*    cerr << "Here" << endl;
    exit(1);
//    double coeff = real_size > 1e5 ? 1.2 : 2;
    double coeff = 2;
    z = (suffixVert *) realloc(z, sizeof(suffixVert) * int(coeff * real_size));
//    for (int i = real_size; i < int(coeff * real_size); ++i)
//        z[i] = suffixVert();
    real_size = int(real_size * coeff);*/
}

inline int next(int v, char c)
{
	return z[v].g[(int)c];
}

class state{
public:
	int v, pos;
	state() {v = 0, pos = 0;}
	state(int _v, int _pos) { v = _v, pos = _pos;}
};

state pos;

state findState(state st, int l, int r)
{
	while (l < r)
	{
//        assert(st.v >= 0 && st.v <= sz);
//        assert(l >= 0 && l < s.size());
//        assert(r >= 0 && r <= s.size());
		if (st.pos == z[st.v].len())
		{
			st.pos = 0;
			st.v = next(st.v, s[l]);
			if (st.v == -1)
            return st;
		} else {
			if (s[z[st.v].l + st.pos] != s[l])
				return state(-1, -1);
			if (r - l < z[st.v].len() - st.pos)
				return state(st.v, st.pos + r - l);
			l += z[st.v].len() - st.pos;
			st.pos = z[st.v].len();
		}
	}
	return st;
}

int cut_edge(state p)
{
//    cerr << p.v << endl;
//    assert(p.v >= 0 && p.v <= sz);
	if (p.pos == z[p.v].len())
		return p.v;
	if (p.pos == 0)
		return z[p.v].par;
	suffixVert tek = z[p.v];
	int last = sz++;
    if (last >= real_size) shrink();
//    assert(last >= 0 && last <= sz);
	z[last] = suffixVert(tek.l, tek.l + p.pos, tek.par);
//    assert(tek.l + p.pos >= 0 && tek.l + p.pos < s.size());
	z[last].g[(int)s[tek.l + p.pos]] = p.v;
//    assert(tek.par >= 0 && tek.par <= sz);
	z[tek.par].g[(int)s[tek.l]] = last;
//    assert(p.v >= 0 && p.v <= sz);
	z[p.v].par = last;
	z[p.v].l += p.pos;
	return last;
}

int make_link(int v)
{
  //  assert(v >= 0 && v <= sz);
	if (z[v].suff != -1)
		return z[v].suff;
	if (z[v].par == -1)
		return 0;
	int suff_par = make_link(z[v].par);
//    assert(suff_par >= 0 && suff_par <= sz);
//    assert(v >= 0 && v <= sz);
	state tek = findState(state(suff_par, z[suff_par].len()), z[v].l + (z[v].par == 0), z[v].r);
//    cerr << "v == " << v << endl;
    int tmp = cut_edge(tek);
//    cerr << "omg: " << tmp << endl;
	z[v].suff = tmp; // HERE PROBLEM
//    cerr << z[v].suff << endl;
	return z[v].suff;
}

void new_vert(int i)
{
	while(1)
	{
		state npos = findState(pos, i, i + 1);
		if (npos.v != -1)
		{
			pos = npos;
			return;
		}
		int p = cut_edge(pos);
		int last = sz++;
//        cerr << "last: " << last << endl;
        if (last >= real_size) shrink();
//        cerr << "last: " << last << " " << real_size << endl;
		z[last] = suffixVert(i, s.size(), p);
 //       cerr << "p: " << p << endl;
		z[p].g[(int)s[i]] = last;
//        cerr << "p2: " << p << endl;

		pos.v = make_link(p);
        if (pos.v == -1) pos.v = 0;
		pos.pos = z[pos.v].len();
		if (!p)
			break;
	}
}

int it = 0;

int l[maxn];

void calc_depth(int v, int cur) {
    cur += z[v].len();
    z[v].depth = cur;

    for (char c = 0; c <= 32; ++c) {
    	if (z[v].g[(int)c] != -1) {
    		calc_depth(z[v].g[(int)c], cur);
            for (int i = z[z[v].g[(int)c]].l; i < z[z[v].g[(int)c]].r; ++i)
                z[v].d[(int)s[i]] += 1;
//            z[v].d[(int)c] += 1;
            for (char c2 = 0; c2 <= 32; ++c2) {
                z[v].d[(int)c2] += z[z[v].g[(int)c]].d[(int)c2];
            }
        }
    }
}

void dfs(int v, int cur) {
    for (int i = z[v].l; i < z[v].r; ++i) {
//        if (z[v].d[0] <= 2 || z[v].d[1] <= 1 || z[v].d[2] == 0)
//            continue;
//        cerr << v << char(s[i] - 4 + 'a') << " " << cur + i - z[v].l + 1 << " " << z[v].d[0] << " " << z[v].d[1] << " " << z[v].d[2] << endl;
        long long tmp = (z[v].d[0] - z[v].d[1]);
        long long tmp2 = (z[v].d[1] - z[v].d[2]);
        long long tmp3 = z[v].d[2];
//        cerr << cur + i - z[v].l << " " << tmp << " " << tmp2 << " " << tmp3 << endl;
        if (tmp > 0 && tmp2 > 0 && tmp3 > 0) {
            l[cur + i - z[v].l] += tmp * tmp2 * tmp3;
        }
//       l[cur + i - z[v].l + 1] += (z[v].d[0] - z[v].d[1] - z) * (z[v].d[1] - 1) * (z[v].d[2] - 0);
    }
    cur += z[v].len();

    for (char c = 0; c <= 32; ++c)
        if (z[v].g[(int)c] != -1)
            dfs(z[v].g[(int)(c)], cur);
}

int main()
{
    ios_base::sync_with_stdio(0);
    string s1, s2, s3;
    cin >> s1 >> s2 >> s3;

    int st_size = maxn;

    real_size = st_size;
//    z = (suffixVert *) malloc(sizeof(suffixVert) * real_size);
//    cerr << z << endl;
//    for (int i = 0; i < real_size; ++i)
//        z[i] = suffixVert();
    z[0] = suffixVert();

    for (int i = 0; i < s1.size(); ++i)
        s1[i] = s1[i] - 'a' + 4;
    for (int i = 0; i < s2.size(); ++i)
        s2[i] = s2[i] - 'a' + 4;
    for (int i = 0; i < s3.size(); ++i)
        s3[i] = s3[i] - 'a' + 4;

    s = s1;
    s.push_back(2);
    s += s2;
    s.push_back(1);
    s += s3;
    s.push_back(0);

	sz = 1;

	for (int i = 0; i < s.size(); ++i) {
//        cerr << i << " " << int(s[0]) << " " << sz << endl;
		new_vert(i);
//        cerr << i << endl;
    }
//    cerr << "size = " << sz << endl;
    calc_depth(0, 0);

//    for (int i = 0; i <= 34; ++i)
//        cerr << "i == " << z[0].d[i] << endl;

    dfs(0, 0);

    for (int i = 0; i < min(s1.size(), min(s2.size(), s3.size())); ++i)
        cout << l[i] << " ";

	return 0;
}


#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <memory.h>
#include <algorithm>
#include <cassert>

using namespace std;

string s;

const int maxn = 1.8 * 1e6;

class suffixVert{
public:
	int l, r, suff, par, depth;
	int g[30];
    int d[30];
	inline int len() {
		return r - l;
	}
	suffixVert() {suff = -1, par = -1, l = 0, r = 0; memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));}
	suffixVert(int _l, int _r, int _par) {suff = -1, l = _l, r = _r, par = _par; memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));}
};

suffixVert z[maxn];
int sz, real_size;

void shrink() {
/*    cerr << "Here" << endl;
    exit(1);
//    double coeff = real_size > 1e5 ? 1.2 : 2;
    double coeff = 2;
    z = (suffixVert *) realloc(z, sizeof(suffixVert) * int(coeff * real_size));
//    for (int i = real_size; i < int(coeff * real_size); ++i)
//        z[i] = suffixVert();
    real_size = int(real_size * coeff);*/
}

inline int next(int v, char c)
{
	return z[v].g[(int)c];
}

class state{
public:
	int v, pos;
	state() {v = 0, pos = 0;}
	state(int _v, int _pos) { v = _v, pos = _pos;}
};

state pos;

state findState(state st, int l, int r)
{
	while (l < r)
	{
//        assert(st.v >= 0 && st.v <= sz);
//        assert(l >= 0 && l < s.size());
//        assert(r >= 0 && r <= s.size());
		if (st.pos == z[st.v].len())
		{
			st.pos = 0;
			st.v = next(st.v, s[l]);
			if (st.v == -1)
            return st;
		} else {
			if (s[z[st.v].l + st.pos] != s[l])
				return state(-1, -1);
			if (r - l < z[st.v].len() - st.pos)
				return state(st.v, st.pos + r - l);
			l += z[st.v].len() - st.pos;
			st.pos = z[st.v].len();
		}
	}
	return st;
}

int cut_edge(state p)
{
//    cerr << p.v << endl;
//    assert(p.v >= 0 && p.v <= sz);
	if (p.pos == z[p.v].len())
		return p.v;
	if (p.pos == 0)
		return z[p.v].par;
	suffixVert tek = z[p.v];
	int last = sz++;
    if (last >= real_size) shrink();
//    assert(last >= 0 && last <= sz);
	z[last] = suffixVert(tek.l, tek.l + p.pos, tek.par);
//    assert(tek.l + p.pos >= 0 && tek.l + p.pos < s.size());
	z[last].g[(int)s[tek.l + p.pos]] = p.v;
//    assert(tek.par >= 0 && tek.par <= sz);
	z[tek.par].g[(int)s[tek.l]] = last;
//    assert(p.v >= 0 && p.v <= sz);
	z[p.v].par = last;
	z[p.v].l += p.pos;
	return last;
}

int make_link(int v)
{
  //  assert(v >= 0 && v <= sz);
	if (z[v].suff != -1)
		return z[v].suff;
	if (z[v].par == -1)
		return 0;
	int suff_par = make_link(z[v].par);
//    assert(suff_par >= 0 && suff_par <= sz);
//    assert(v >= 0 && v <= sz);
	state tek = findState(state(suff_par, z[suff_par].len()), z[v].l + (z[v].par == 0), z[v].r);
//    cerr << "v == " << v << endl;
    int tmp = cut_edge(tek);
//    cerr << "omg: " << tmp << endl;
	z[v].suff = tmp; // HERE PROBLEM
//    cerr << z[v].suff << endl;
	return z[v].suff;
}

void new_vert(int i)
{
	while(1)
	{
		state npos = findState(pos, i, i + 1);
		if (npos.v != -1)
		{
			pos = npos;
			return;
		}
		int p = cut_edge(pos);
		int last = sz++;
//        cerr << "last: " << last << endl;
        if (last >= real_size) shrink();
//        cerr << "last: " << last << " " << real_size << endl;
		z[last] = suffixVert(i, s.size(), p);
 //       cerr << "p: " << p << endl;
		z[p].g[(int)s[i]] = last;
//        cerr << "p2: " << p << endl;

		pos.v = make_link(p);
        if (pos.v == -1) pos.v = 0;
		pos.pos = z[pos.v].len();
		if (!p)
			break;
	}
}

int it = 0;

int l[maxn];

void calc_depth(int v, int cur) {
    cur += z[v].len();
    z[v].depth = cur;

    for (char c = 0; c <= 29; ++c) {
    	if (z[v].g[(int)c] != -1) {
    		calc_depth(z[v].g[(int)c], cur);
            for (int i = z[z[v].g[(int)c]].l; i < z[z[v].g[(int)c]].r; ++i)
                z[v].d[(int)s[i]] += 1;
            z[v].d[0] += z[z[v].g[(int)c]].d[0];
            z[v].d[1] += z[z[v].g[(int)c]].d[1];
            z[v].d[2] += z[z[v].g[(int)c]].d[2];
//            z[v].d[(int)c] += 1;
//            for (char c2 = 0; c2 <= 29; ++c2) {
//                z[v].d[(int)c2] += z[z[v].g[(int)c]].d[(int)c2];
//            }
        }
    }
}

void dfs(int v, int cur) {
    for (int i = z[v].l; i < z[v].r; ++i) {
//        if (z[v].d[0] <= 2 || z[v].d[1] <= 1 || z[v].d[2] == 0)
//            continue;
//        cerr << v << char(s[i] - 4 + 'a') << " " << cur + i - z[v].l + 1 << " " << z[v].d[0] << " " << z[v].d[1] << " " << z[v].d[2] << endl;
        long long tmp = (z[v].d[0] - z[v].d[1]);
        long long tmp2 = (z[v].d[1] - z[v].d[2]);
        long long tmp3 = z[v].d[2];
//        cerr << cur + i - z[v].l << " " << tmp << " " << tmp2 << " " << tmp3 << endl;
        if (tmp > 0 && tmp2 > 0 && tmp3 > 0) {
            l[cur + i - z[v].l] += tmp * tmp2 * tmp3;
        }
//       l[cur + i - z[v].l + 1] += (z[v].d[0] - z[v].d[1] - z) * (z[v].d[1] - 1) * (z[v].d[2] - 0);
    }
    cur += z[v].len();

    for (char c = 0; c <= 29; ++c)
        if (z[v].g[(int)c] != -1)
            dfs(z[v].g[(int)(c)], cur);
}

int main()
{
    ios_base::sync_with_stdio(0);
    string s1, s2, s3;
    cin >> s1 >> s2 >> s3;

    int st_size = maxn;

    real_size = st_size;
//    z = (suffixVert *) malloc(sizeof(suffixVert) * real_size);
//    cerr << z << endl;
//    for (int i = 0; i < real_size; ++i)
//        z[i] = suffixVert();
    z[0] = suffixVert();

    for (int i = 0; i < s1.size(); ++i)
        s1[i] = s1[i] - 'a' + 3;
    for (int i = 0; i < s2.size(); ++i)
        s2[i] = s2[i] - 'a' + 3;
    for (int i = 0; i < s3.size(); ++i)
        s3[i] = s3[i] - 'a' + 3;

    s = s1;
    s.push_back(2);
    s += s2;
    s.push_back(1);
    s += s3;
    s.push_back(0);

	sz = 1;

    cerr << s.size() << endl;

	for (int i = 0; i < s.size(); ++i) {
//        cerr << i << " " << int(s[0]) << " " << sz << endl;
		new_vert(i);
//        cerr << i << endl;
    }
    calc_depth(0, 0);

//    for (int i = 0; i <= 34; ++i)
//        cerr << "i == " << z[0].d[i] << endl;

    cerr << "size = " << sz << endl;
    dfs(0, 0);

    for (int i = 0; i < min(s1.size(), min(s2.size(), s3.size())); ++i)
        cout << l[i] << " ";

	return 0;
}


#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <memory.h>
#include <algorithm>
#include <cassert>

using namespace std;

string s;

const int maxn = 2 * 1e6;

class suffixVert{
public:
	int l, r, suff, par, depth;
	int g[30];
    int d[30];
	inline int len() {
		return r - l;
	}
	suffixVert() {suff = -1, par = -1, l = 0, r = 0; memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));}
	suffixVert(int _l, int _r, int _par) {suff = -1, l = _l, r = _r, par = _par; memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));}
};

suffixVert z[maxn];
int sz, real_size;

void shrink() {
/*    cerr << "Here" << endl;
    exit(1);
//    double coeff = real_size > 1e5 ? 1.2 : 2;
    double coeff = 2;
    z = (suffixVert *) realloc(z, sizeof(suffixVert) * int(coeff * real_size));
//    for (int i = real_size; i < int(coeff * real_size); ++i)
//        z[i] = suffixVert();
    real_size = int(real_size * coeff);*/
}

inline int next(int v, char c)
{
	return z[v].g[(int)c];
}

class state{
public:
	int v, pos;
	state() {v = 0, pos = 0;}
	state(int _v, int _pos) { v = _v, pos = _pos;}
};

state pos;

state findState(state st, int l, int r)
{
	while (l < r)
	{
//        assert(st.v >= 0 && st.v <= sz);
//        assert(l >= 0 && l < s.size());
//        assert(r >= 0 && r <= s.size());
		if (st.pos == z[st.v].len())
		{
			st.pos = 0;
			st.v = next(st.v, s[l]);
			if (st.v == -1)
            return st;
		} else {
			if (s[z[st.v].l + st.pos] != s[l])
				return state(-1, -1);
			if (r - l < z[st.v].len() - st.pos)
				return state(st.v, st.pos + r - l);
			l += z[st.v].len() - st.pos;
			st.pos = z[st.v].len();
		}
	}
	return st;
}

int cut_edge(state p)
{
//    cerr << p.v << endl;
//    assert(p.v >= 0 && p.v <= sz);
	if (p.pos == z[p.v].len())
		return p.v;
	if (p.pos == 0)
		return z[p.v].par;
	suffixVert tek = z[p.v];
	int last = sz++;
    if (last >= real_size) shrink();
//    assert(last >= 0 && last <= sz);
	z[last] = suffixVert(tek.l, tek.l + p.pos, tek.par);
//    assert(tek.l + p.pos >= 0 && tek.l + p.pos < s.size());
	z[last].g[(int)s[tek.l + p.pos]] = p.v;
//    assert(tek.par >= 0 && tek.par <= sz);
	z[tek.par].g[(int)s[tek.l]] = last;
//    assert(p.v >= 0 && p.v <= sz);
	z[p.v].par = last;
	z[p.v].l += p.pos;
	return last;
}

int make_link(int v)
{
  //  assert(v >= 0 && v <= sz);
	if (z[v].suff != -1)
		return z[v].suff;
	if (z[v].par == -1)
		return 0;
	int suff_par = make_link(z[v].par);
//    assert(suff_par >= 0 && suff_par <= sz);
//    assert(v >= 0 && v <= sz);
	state tek = findState(state(suff_par, z[suff_par].len()), z[v].l + (z[v].par == 0), z[v].r);
//    cerr << "v == " << v << endl;
    int tmp = cut_edge(tek);
//    cerr << "omg: " << tmp << endl;
	z[v].suff = tmp; // HERE PROBLEM
//    cerr << z[v].suff << endl;
	return z[v].suff;
}

void new_vert(int i)
{
	while(1)
	{
		state npos = findState(pos, i, i + 1);
		if (npos.v != -1)
		{
			pos = npos;
			return;
		}
		int p = cut_edge(pos);
		int last = sz++;
//        cerr << "last: " << last << endl;
        if (last >= real_size) shrink();
//        cerr << "last: " << last << " " << real_size << endl;
		z[last] = suffixVert(i, s.size(), p);
 //       cerr << "p: " << p << endl;
		z[p].g[(int)s[i]] = last;
//        cerr << "p2: " << p << endl;

		pos.v = make_link(p);
        if (pos.v == -1) pos.v = 0;
		pos.pos = z[pos.v].len();
		if (!p)
			break;
	}
}

int it = 0;

int l[maxn];

void calc_depth(int v, int cur) {
    cur += z[v].len();
    z[v].depth = cur;

    for (char c = 0; c <= 29; ++c) {
    	if (z[v].g[(int)c] != -1) {
    		calc_depth(z[v].g[(int)c], cur);
            for (int i = z[z[v].g[(int)c]].l; i < z[z[v].g[(int)c]].r; ++i)
                z[v].d[(int)s[i]] += 1;
            z[v].d[0] += z[z[v].g[(int)c]].d[0];
            z[v].d[1] += z[z[v].g[(int)c]].d[1];
            z[v].d[2] += z[z[v].g[(int)c]].d[2];
//            z[v].d[(int)c] += 1;
//            for (char c2 = 0; c2 <= 29; ++c2) {
//                z[v].d[(int)c2] += z[z[v].g[(int)c]].d[(int)c2];
//            }
        }
    }
}

void dfs(int v, int cur) {
    for (int i = z[v].l; i < z[v].r; ++i) {
//        if (z[v].d[0] <= 2 || z[v].d[1] <= 1 || z[v].d[2] == 0)
//            continue;
//        cerr << v << char(s[i] - 4 + 'a') << " " << cur + i - z[v].l + 1 << " " << z[v].d[0] << " " << z[v].d[1] << " " << z[v].d[2] << endl;
        long long tmp = (z[v].d[0] - z[v].d[1]);
        long long tmp2 = (z[v].d[1] - z[v].d[2]);
        long long tmp3 = z[v].d[2];
//        cerr << cur + i - z[v].l << " " << tmp << " " << tmp2 << " " << tmp3 << endl;
        if (tmp > 0 && tmp2 > 0 && tmp3 > 0) {
            l[cur + i - z[v].l] += tmp * tmp2 * tmp3;
        }
//       l[cur + i - z[v].l + 1] += (z[v].d[0] - z[v].d[1] - z) * (z[v].d[1] - 1) * (z[v].d[2] - 0);
    }
    cur += z[v].len();

    for (char c = 0; c <= 29; ++c)
        if (z[v].g[(int)c] != -1)
            dfs(z[v].g[(int)(c)], cur);
}

string s1, s2, s3;
int main()
{
    ios_base::sync_with_stdio(0);
    cin >> s1 >> s2 >> s3;

    int st_size = maxn;

    real_size = st_size;
//    z = (suffixVert *) malloc(sizeof(suffixVert) * real_size);
//    cerr << z << endl;
//    for (int i = 0; i < real_size; ++i)
//        z[i] = suffixVert();
    z[0] = suffixVert();

    for (int i = 0; i < s1.size(); ++i)
        s1[i] = s1[i] - 'a' + 3;
    for (int i = 0; i < s2.size(); ++i)
        s2[i] = s2[i] - 'a' + 3;
    for (int i = 0; i < s3.size(); ++i)
        s3[i] = s3[i] - 'a' + 3;

    s = s1;
    s.push_back(2);
    s += s2;
    s.push_back(1);
    s += s3;
    s.push_back(0);

	sz = 1;

    cerr << s.size() << endl;

	for (int i = 0; i < s.size(); ++i) {
//        cerr << i << " " << int(s[0]) << " " << sz << endl;
		new_vert(i);
//        cerr << i << endl;
    }
    calc_depth(0, 0);

//    for (int i = 0; i <= 34; ++i)
//        cerr << "i == " << z[0].d[i] << endl;

    cerr << "size = " << sz << endl;
    dfs(0, 0);

    for (int i = 0; i < min(s1.size(), min(s2.size(), s3.size())); ++i)
        cout << l[i] << " ";

	return 0;
}


#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <memory.h>
#include <algorithm>
#include <cassert>
#include <set>

using namespace std;

string s;

const int maxn = 2 * 1e6;

const int md = 1e9 + 7;

class suffixVert{
public:
	int l, r, suff, par, depth;
//	int g[30];
//    int d[30];
    map<int, int> g;
    map<int, int> d;
	inline int len() {
		return r - l;
	}
	suffixVert() {suff = -1, par = -1, l = 0, r = 0;/* memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));*/}
	suffixVert(int _l, int _r, int _par) {suff = -1, l = _l, r = _r, par = _par;/*memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));*/}
};

suffixVert z[maxn];
int sz, real_size;
int dyn[maxn][3];

void shrink() {
/*    cerr << "Here" << endl;
    exit(1);
//    double coeff = real_size > 1e5 ? 1.2 : 2;
    double coeff = 2;
    z = (suffixVert *) realloc(z, sizeof(suffixVert) * int(coeff * real_size));
//    for (int i = real_size; i < int(coeff * real_size); ++i)
//        z[i] = suffixVert();
    real_size = int(real_size * coeff);*/
}

inline int next(int v, char c)
{
    if (z[v].g.find((int)c) == z[v].g.end())
        return -1;
	return z[v].g[(int)c];
}

class state{
public:
	int v, pos;
	state() {v = 0, pos = 0;}
	state(int _v, int _pos) { v = _v, pos = _pos;}
};

state pos;

state findState(state st, int l, int r)
{
	while (l < r)
	{
//        assert(st.v >= 0 && st.v <= sz);
//        assert(l >= 0 && l < s.size());
//        assert(r >= 0 && r <= s.size());
		if (st.pos == z[st.v].len())
		{
			st.pos = 0;
			st.v = next(st.v, s[l]);
			if (st.v == -1)
            return st;
		} else {
			if (s[z[st.v].l + st.pos] != s[l])
				return state(-1, -1);
			if (r - l < z[st.v].len() - st.pos)
				return state(st.v, st.pos + r - l);
			l += z[st.v].len() - st.pos;
			st.pos = z[st.v].len();
		}
	}
	return st;
}

int cut_edge(state p)
{
//    cerr << p.v << endl;
//    assert(p.v >= 0 && p.v <= sz);
	if (p.pos == z[p.v].len())
		return p.v;
	if (p.pos == 0)
		return z[p.v].par;
	suffixVert tek = z[p.v];
	int last = sz++;
    if (last >= real_size) shrink();
//    assert(last >= 0 && last <= sz);
	z[last] = suffixVert(tek.l, tek.l + p.pos, tek.par);
//    assert(tek.l + p.pos >= 0 && tek.l + p.pos < s.size());
	z[last].g[(int)s[tek.l + p.pos]] = p.v;
//    assert(tek.par >= 0 && tek.par <= sz);
	z[tek.par].g[(int)s[tek.l]] = last;
//    assert(p.v >= 0 && p.v <= sz);
	z[p.v].par = last;
	z[p.v].l += p.pos;
	return last;
}

int make_link(int v)
{
  //  assert(v >= 0 && v <= sz);
	if (z[v].suff != -1)
		return z[v].suff;
	if (z[v].par == -1)
		return 0;
	int suff_par = make_link(z[v].par);
//    assert(suff_par >= 0 && suff_par <= sz);
//    assert(v >= 0 && v <= sz);
	state tek = findState(state(suff_par, z[suff_par].len()), z[v].l + (z[v].par == 0), z[v].r);
//    cerr << "v == " << v << endl;
    int tmp = cut_edge(tek);
//    cerr << "omg: " << tmp << endl;
	z[v].suff = tmp; // HERE PROBLEM
//    cerr << z[v].suff << endl;
	return z[v].suff;
}

void new_vert(int i)
{
	while(1)
	{
		state npos = findState(pos, i, i + 1);
		if (npos.v != -1)
		{
			pos = npos;
			return;
		}
		int p = cut_edge(pos);
		int last = sz++;
//        cerr << "last: " << last << endl;
        if (last >= real_size) shrink();
//        cerr << "last: " << last << " " << real_size << endl;
		z[last] = suffixVert(i, s.size(), p);
 //       cerr << "p: " << p << endl;
		z[p].g[(int)s[i]] = last;
//        cerr << "p2: " << p << endl;

		pos.v = make_link(p);
        if (pos.v == -1) pos.v = 0;
		pos.pos = z[pos.v].len();
		if (!p)
			break;
	}
}

int it = 0;

int t[maxn * 8];

int calc_d(int l, int r, int c) {
    if (l == 0)
        return dyn[r - 1][c];
//    cerr << l << " " << r << " " << c << " " << dyn[r - 1][c] - dyn[l - 1][c] << endl;
    return dyn[r - 1][c] - dyn[l - 1][c];
}

void calc_depth(int v, int cur) {
    cur += z[v].len();
    z[v].depth = cur;

    for (map<int, int>::const_iterator it = z[v].g.begin(); it != z[v].g.end(); ++it) {
//    for (char c = 0; c <= 29; ++c) {
//    	if (next(v, c) != -1) {
//            int to = next(v, c);
            int to = it->second;
            char c = it->first;
    		calc_depth(to, cur);
/*            int tmp[3];
            tmp[0] = tmp[1] = tmp[2] = 0;
            for (int i = z[to].l; i < z[to].r; ++i)
                if ((int)s[i] <= 2)
                    tmp[s[i]] += 1;*/
            z[v].d[0] += calc_d(z[to].l, z[to].r, 0);
            z[v].d[1] += calc_d(z[to].l, z[to].r, 1);
            z[v].d[2] += calc_d(z[to].l, z[to].r, 2);
//            cerr << calc_d(z[to].l, z[to].r, 2) << " " << tmp[2] << endl;
            z[v].d[0] += z[to].d[0];
            z[v].d[1] += z[to].d[1];
            z[v].d[2] += z[to].d[2];
//            z[v].d[(int)c] += 1;
//            for (char c2 = 0; c2 <= 29; ++c2) {
//                z[v].d[(int)c2] += z[z[v].g[(int)c]].d[(int)c2];
//            }
        }
//    }
}

void update (int v, int tl, int tr, int l, int r, int add) {
	if (l > r)
		return;
//    assert(l == r);
//    cerr << v << " " << l << " " << r << " " << tl << " " << tr << endl;
//    return;
	if (l == tl && tr == r)
		t[v] = (t[v] + add) % md;
	else {
		int tm = (tl + tr) / 2;
		update (v * 2, tl, tm, l, min(r, tm), add);
		update (v * 2 + 1, tm + 1, tr, max(l, tm + 1), r, add);
	}
}
int get (int v, int tl, int tr, int pos) {
	if (tl == tr)
		return t[v];
	int tm = (tl + tr) / 2;
	if (pos <= tm)
		return (t[v] + get (v*2, tl, tm, pos)) % md;
	else
		return (t[v] + get (v*2+1, tm+1, tr, pos)) % md;
}

void dfs(int v, int cur) {
//    for (int i = z[v].l; i < z[v].r; ++i) {
//        if (z[v].d[0] <= 2 || z[v].d[1] <= 1 || z[v].d[2] == 0)
//            continue;
//        cerr << v << char(s[i] - 4 + 'a') << " " << cur + i - z[v].l + 1 << " " << z[v].d[0] << " " << z[v].d[1] << " " << z[v].d[2] << endl;
        long long tmp1 = (z[v].d[0] - z[v].d[1]);
        long long tmp2 = (z[v].d[1] - z[v].d[2]);
        long long tmp3 = z[v].d[2];
//        cerr << cur + i - z[v].l << " " << tmp << " " << tmp2 << " " << tmp3 << endl;
        if (tmp1 > 0 && tmp2 > 0 && tmp3 > 0 && z[v].len() > 0) {
/*            node tmp;
            tmp.l = cur;
            tmp.r = cur + z[v].len();*/
            int tmp_value = (tmp1 * 1ll * tmp2 * 1ll * tmp3) % md;
            update(1, 0, (1 << 20), cur, cur + z[v].len() - 1, tmp_value);
//            ans.push_back(tmp);
//            l[cur + i - z[v].l] = (l[cur + i - z[v].l] + tmp * 1ll * tmp2 * 1ll * tmp3) % md;
        }
//       l[cur + i - z[v].l + 1] += (z[v].d[0] - z[v].d[1] - z) * (z[v].d[1] - 1) * (z[v].d[2] - 0);
//    }
    cur += z[v].len();

//    for (char c = 0; c <= 29; ++c)
    for (map<int, int>::const_iterator it = z[v].g.begin(); it != z[v].g.end(); ++it)
//        if (next(v, c) != -1)
//            dfs(next(v, c), cur);
        dfs(it->second, cur);
}

string s1, s2, s3;
int main()
{
    ios_base::sync_with_stdio(0);
    cin >> s1 >> s2 >> s3;

    int st_size = maxn;

    real_size = st_size;
//    z = (suffixVert *) malloc(sizeof(suffixVert) * real_size);
//    cerr << z << endl;
//    for (int i = 0; i < real_size; ++i)
//        z[i] = suffixVert();
    z[0] = suffixVert();

    for (int i = 0; i < s1.size(); ++i)
        s1[i] = s1[i] - 'a' + 3;
    for (int i = 0; i < s2.size(); ++i)
        s2[i] = s2[i] - 'a' + 3;
    for (int i = 0; i < s3.size(); ++i)
        s3[i] = s3[i] - 'a' + 3;

    s = s1;
    s.push_back(2);
    s += s2;
    s.push_back(1);
    s += s3;
    s.push_back(0);

    if (s[0] <= 2)
        dyn[0][s[0]] = 1;
    for (int i = 1; i < s.size(); ++i) {
        for (int j = 0; j <= 2; ++j)
            dyn[i][j] = dyn[i - 1][j];
        if (s[i] <= 2)
            dyn[i][s[i]]++;
    }
/*    for (int i = 0; i < s.size(); ++i)
        cerr << (int)s[i] << " ";
    cerr << endl;
    for (int i = 0; i < s.size(); ++i)
        cerr << dyn[i][0] << " " << dyn[i][1] << " " << dyn[i][2] << endl;*/

	sz = 1;

    cerr << s.size() << endl;

	for (int i = 0; i < s.size(); ++i) {
//        cerr << i << " " << int(s[0]) << " " << sz << endl;
		new_vert(i);
//        cerr << i << endl;
    }
    cerr << sz << endl;
    calc_depth(0, 0);

//    for (int i = 0; i <= 34; ++i)
//        cerr << "i == " << z[0].d[i] << endl;

    cerr << "size = " << sz << endl;
    dfs(0, 0);

//    sort(ans.begin(), ans.end(), cmp);

//    for (int i = 0; i < ans.size(); ++i)
//        cerr << ans[i].l << " " << ans[i].r << " " << ans[i].value << endl;

    long long cur = 0;
    int p = 0;
    set<pair<int, long long> > z_s;
    for (int i = 0; i < min(s1.size(), min(s2.size(), s3.size())); ++i) {
/*        while (z_s.size() > 0 && z_s.begin()->first <= i) {
            cur -= z_s.begin()->second;
            z_s.erase(z_s.begin());
        }
        while (p < ans.size() && ans[p].l <= i) {
            cur += ans[p].value;
            z_s.insert(make_pair(ans[p].r, ans[p].value));
            ++p;
        }
        cout << cur % md << " ";*/
        cout << get(1, 0, (1<<20), i) << " ";
    }

//    for (int i = 0; i < min(s1.size(), min(s2.size(), s3.size())); ++i)
//        cout << l[i] << " ";

	return 0;
}


#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <memory.h>
#include <algorithm>
#include <cassert>

using namespace std;

string s;

const int maxn = 1e6 + 15;

class suffixVert{
public:
	int l, r, suff, par, depth;
	int g[30];
    int d[30];
	inline int len() {
		return r - l;
	}
	suffixVert() {suff = -1, par = -1, l = 0, r = 0; memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));}
	suffixVert(int _l, int _r, int _par) {suff = -1, l = _l, r = _r, par = _par; memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));}
};

suffixVert z[maxn];
int sz, real_size;

void shrink() {
/*    cerr << "Here" << endl;
    exit(1);
//    double coeff = real_size > 1e5 ? 1.2 : 2;
    double coeff = 2;
    z = (suffixVert *) realloc(z, sizeof(suffixVert) * int(coeff * real_size));
//    for (int i = real_size; i < int(coeff * real_size); ++i)
//        z[i] = suffixVert();
    real_size = int(real_size * coeff);*/
}

inline int next(int v, char c)
{
	return z[v].g[(int)c];
}

class state{
public:
	int v, pos;
	state() {v = 0, pos = 0;}
	state(int _v, int _pos) { v = _v, pos = _pos;}
};

state pos;

state findState(state st, int l, int r)
{
	while (l < r)
	{
//        assert(st.v >= 0 && st.v <= sz);
//        assert(l >= 0 && l < s.size());
//        assert(r >= 0 && r <= s.size());
		if (st.pos == z[st.v].len())
		{
			st.pos = 0;
			st.v = next(st.v, s[l]);
			if (st.v == -1)
            return st;
		} else {
			if (s[z[st.v].l + st.pos] != s[l])
				return state(-1, -1);
			if (r - l < z[st.v].len() - st.pos)
				return state(st.v, st.pos + r - l);
			l += z[st.v].len() - st.pos;
			st.pos = z[st.v].len();
		}
	}
	return st;
}

int cut_edge(state p)
{
//    cerr << p.v << endl;
//    assert(p.v >= 0 && p.v <= sz);
	if (p.pos == z[p.v].len())
		return p.v;
	if (p.pos == 0)
		return z[p.v].par;
	suffixVert tek = z[p.v];
	int last = sz++;
    if (last >= real_size) shrink();
//    assert(last >= 0 && last <= sz);
	z[last] = suffixVert(tek.l, tek.l + p.pos, tek.par);
//    assert(tek.l + p.pos >= 0 && tek.l + p.pos < s.size());
	z[last].g[(int)s[tek.l + p.pos]] = p.v;
//    assert(tek.par >= 0 && tek.par <= sz);
	z[tek.par].g[(int)s[tek.l]] = last;
//    assert(p.v >= 0 && p.v <= sz);
	z[p.v].par = last;
	z[p.v].l += p.pos;
	return last;
}

int make_link(int v)
{
  //  assert(v >= 0 && v <= sz);
	if (z[v].suff != -1)
		return z[v].suff;
	if (z[v].par == -1)
		return 0;
	int suff_par = make_link(z[v].par);
//    assert(suff_par >= 0 && suff_par <= sz);
//    assert(v >= 0 && v <= sz);
	state tek = findState(state(suff_par, z[suff_par].len()), z[v].l + (z[v].par == 0), z[v].r);
//    cerr << "v == " << v << endl;
    int tmp = cut_edge(tek);
//    cerr << "omg: " << tmp << endl;
	z[v].suff = tmp; // HERE PROBLEM
//    cerr << z[v].suff << endl;
	return z[v].suff;
}

void new_vert(int i)
{
	while(1)
	{
		state npos = findState(pos, i, i + 1);
		if (npos.v != -1)
		{
			pos = npos;
			return;
		}
		int p = cut_edge(pos);
		int last = sz++;
//        cerr << "last: " << last << endl;
        if (last >= real_size) shrink();
//        cerr << "last: " << last << " " << real_size << endl;
		z[last] = suffixVert(i, s.size(), p);
 //       cerr << "p: " << p << endl;
		z[p].g[(int)s[i]] = last;
//        cerr << "p2: " << p << endl;

		pos.v = make_link(p);
        if (pos.v == -1) pos.v = 0;
		pos.pos = z[pos.v].len();
		if (!p)
			break;
	}
}

int it = 0;

int l[maxn];

void calc_depth(int v, int cur) {
    cur += z[v].len();
    z[v].depth = cur;

    for (char c = 0; c <= 29; ++c) {
    	if (z[v].g[(int)c] != -1) {
    		calc_depth(z[v].g[(int)c], cur);
            for (int i = z[z[v].g[(int)c]].l; i < z[z[v].g[(int)c]].r; ++i)
                z[v].d[(int)s[i]] += 1;
//            z[v].d[(int)c] += 1;
            for (char c2 = 0; c2 <= 29; ++c2) {
                z[v].d[(int)c2] += z[z[v].g[(int)c]].d[(int)c2];
            }
        }
    }
}

void dfs(int v, int cur) {
    for (int i = z[v].l; i < z[v].r; ++i) {
//        if (z[v].d[0] <= 2 || z[v].d[1] <= 1 || z[v].d[2] == 0)
//            continue;
//        cerr << v << char(s[i] - 4 + 'a') << " " << cur + i - z[v].l + 1 << " " << z[v].d[0] << " " << z[v].d[1] << " " << z[v].d[2] << endl;
        long long tmp = (z[v].d[0] - z[v].d[1]);
        long long tmp2 = (z[v].d[1] - z[v].d[2]);
        long long tmp3 = z[v].d[2];
//        cerr << cur + i - z[v].l << " " << tmp << " " << tmp2 << " " << tmp3 << endl;
        if (tmp > 0 && tmp2 > 0 && tmp3 > 0) {
            l[cur + i - z[v].l] += tmp * tmp2 * tmp3;
        }
//       l[cur + i - z[v].l + 1] += (z[v].d[0] - z[v].d[1] - z) * (z[v].d[1] - 1) * (z[v].d[2] - 0);
    }
    cur += z[v].len();

    for (char c = 0; c <= 29; ++c)
        if (z[v].g[(int)c] != -1)
            dfs(z[v].g[(int)(c)], cur);
}

int main()
{
    ios_base::sync_with_stdio(0);
    string s1, s2, s3;
    cin >> s1 >> s2 >> s3;

    int st_size = maxn;

    real_size = st_size;
//    z = (suffixVert *) malloc(sizeof(suffixVert) * real_size);
//    cerr << z << endl;
//    for (int i = 0; i < real_size; ++i)
//        z[i] = suffixVert();
    z[0] = suffixVert();

    for (int i = 0; i < s1.size(); ++i)
        s1[i] = s1[i] - 'a' + 3;
    for (int i = 0; i < s2.size(); ++i)
        s2[i] = s2[i] - 'a' + 3;
    for (int i = 0; i < s3.size(); ++i)
        s3[i] = s3[i] - 'a' + 3;

    s = s1;
    s.push_back(2);
    s += s2;
    s.push_back(1);
    s += s3;
    s.push_back(0);

	sz = 1;

	for (int i = 0; i < s.size(); ++i) {
//        cerr << i << " " << int(s[0]) << " " << sz << endl;
		new_vert(i);
//        cerr << i << endl;
    }
//    cerr << "size = " << sz << endl;
    calc_depth(0, 0);

//    for (int i = 0; i <= 34; ++i)
//        cerr << "i == " << z[0].d[i] << endl;

    dfs(0, 0);

    for (int i = 0; i < min(s1.size(), min(s2.size(), s3.size())); ++i)
        cout << l[i] << " ";

	return 0;
}


#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <memory.h>
#include <algorithm>
#include <cassert>

using namespace std;

string s;

const int maxn = 1e5 * 3 + 15;

class suffixVert{
public:
	int l, r, suff, par, depth;
	int g[32];
    int d[32];
	inline int len() {
		return r - l;
	}
	suffixVert() {suff = -1, par = -1, l = 0, r = 0; memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));}
	suffixVert(int _l, int _r, int _par) {suff = -1, l = _l, r = _r, par = _par; memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));}
};

suffixVert * z;
int sz, real_size;

void shrink() {
//    double coeff = real_size > 1e5 ? 1.2 : 2;
    double coeff = 2;
    z = (suffixVert *) realloc(z, sizeof(suffixVert) * int(coeff * real_size));
//    for (int i = real_size; i < int(coeff * real_size); ++i)
//        z[i] = suffixVert();
    real_size = int(real_size * coeff);
}

inline int next(int v, char c)
{
	return z[v].g[(int)c];
}

class state{
public:
	int v, pos;
	state() {v = 0, pos = 0;}
	state(int _v, int _pos) { v = _v, pos = _pos;}
};

state pos;

state findState(state st, int l, int r)
{
	while (l < r)
	{
//        assert(st.v >= 0 && st.v <= sz);
//        assert(l >= 0 && l < s.size());
//        assert(r >= 0 && r <= s.size());
		if (st.pos == z[st.v].len())
		{
			st.pos = 0;
			st.v = next(st.v, s[l]);
			if (st.v == -1)
            return st;
		} else {
			if (s[z[st.v].l + st.pos] != s[l])
				return state(-1, -1);
			if (r - l < z[st.v].len() - st.pos)
				return state(st.v, st.pos + r - l);
			l += z[st.v].len() - st.pos;
			st.pos = z[st.v].len();
		}
	}
	return st;
}

int cut_edge(state p)
{
//    cerr << p.v << endl;
//    assert(p.v >= 0 && p.v <= sz);
	if (p.pos == z[p.v].len())
		return p.v;
	if (p.pos == 0)
		return z[p.v].par;
	suffixVert tek = z[p.v];
	int last = sz++;
    if (last >= real_size) shrink();
//    assert(last >= 0 && last <= sz);
	z[last] = suffixVert(tek.l, tek.l + p.pos, tek.par);
//    assert(tek.l + p.pos >= 0 && tek.l + p.pos < s.size());
	z[last].g[(int)s[tek.l + p.pos]] = p.v;
//    assert(tek.par >= 0 && tek.par <= sz);
	z[tek.par].g[(int)s[tek.l]] = last;
//    assert(p.v >= 0 && p.v <= sz);
	z[p.v].par = last;
	z[p.v].l += p.pos;
	return last;
}

int make_link(int v)
{
  //  assert(v >= 0 && v <= sz);
	if (z[v].suff != -1)
		return z[v].suff;
	if (z[v].par == -1)
		return 0;
	int suff_par = make_link(z[v].par);
//    assert(suff_par >= 0 && suff_par <= sz);
//    assert(v >= 0 && v <= sz);
	state tek = findState(state(suff_par, z[suff_par].len()), z[v].l + (z[v].par == 0), z[v].r);
//    cerr << "v == " << v << endl;
    int tmp = cut_edge(tek);
//    cerr << "omg: " << tmp << endl;
	z[v].suff = tmp; // HERE PROBLEM
//    cerr << z[v].suff << endl;
	return z[v].suff;
}

void new_vert(int i)
{
	while(1)
	{
		state npos = findState(pos, i, i + 1);
		if (npos.v != -1)
		{
			pos = npos;
			return;
		}
		int p = cut_edge(pos);
		int last = sz++;
//        cerr << "last: " << last << endl;
        if (last >= real_size) shrink();
//        cerr << "last: " << last << " " << real_size << endl;
		z[last] = suffixVert(i, s.size(), p);
 //       cerr << "p: " << p << endl;
		z[p].g[(int)s[i]] = last;
//        cerr << "p2: " << p << endl;

		pos.v = make_link(p);
        if (pos.v == -1) pos.v = 0;
		pos.pos = z[pos.v].len();
		if (!p)
			break;
	}
}

int it = 0;

int l[maxn];

void calc_depth(int v, int cur) {
    cur += z[v].len();
    z[v].depth = cur;

    for (char c = 0; c <= 34; ++c) {
    	if (z[v].g[(int)c] != -1) {
    		calc_depth(z[v].g[(int)c], cur);
            for (int i = z[z[v].g[(int)c]].l; i < z[z[v].g[(int)c]].r; ++i)
                z[v].d[(int)s[i]] += 1;
//            z[v].d[(int)c] += 1;
            for (char c2 = 0; c2 <= 34; ++c2) {
                z[v].d[(int)c2] += z[z[v].g[(int)c]].d[(int)c2];
            }
        }
    }
}

void dfs(int v, int cur) {
    for (int i = z[v].l; i < z[v].r; ++i) {
//        if (z[v].d[0] <= 2 || z[v].d[1] <= 1 || z[v].d[2] == 0)
//            continue;
//        cerr << v << char(s[i] - 4 + 'a') << " " << cur + i - z[v].l + 1 << " " << z[v].d[0] << " " << z[v].d[1] << " " << z[v].d[2] << endl;
        long long tmp = (z[v].d[0] - z[v].d[1]);
        long long tmp2 = (z[v].d[1] - z[v].d[2]);
        long long tmp3 = z[v].d[2];
//        cerr << cur + i - z[v].l << " " << tmp << " " << tmp2 << " " << tmp3 << endl;
        if (tmp > 0 && tmp2 > 0 && tmp3 > 0) {
            l[cur + i - z[v].l] += tmp * tmp2 * tmp3;
        }
//       l[cur + i - z[v].l + 1] += (z[v].d[0] - z[v].d[1] - z) * (z[v].d[1] - 1) * (z[v].d[2] - 0);
    }
    cur += z[v].len();

    for (char c = 0; c <= 34; ++c)
        if (z[v].g[(int)c] != -1)
            dfs(z[v].g[(int)(c)], cur);
}

int main()
{
    ios_base::sync_with_stdio(0);
    string s1, s2, s3;
    cin >> s1 >> s2 >> s3;

    int st_size = 600000;

    real_size = st_size;
    z = (suffixVert *) malloc(sizeof(suffixVert) * real_size);
//    cerr << z << endl;
//    for (int i = 0; i < real_size; ++i)
//        z[i] = suffixVert();
    z[0] = suffixVert();

    for (int i = 0; i < s1.size(); ++i)
        s1[i] = s1[i] - 'a' + 4;
    for (int i = 0; i < s2.size(); ++i)
        s2[i] = s2[i] - 'a' + 4;
    for (int i = 0; i < s3.size(); ++i)
        s3[i] = s3[i] - 'a' + 4;

    s = s1;
    s.push_back(2);
    s += s2;
    s.push_back(1);
    s += s3;
    s.push_back(0);

	sz = 1;

	for (int i = 0; i < s.size(); ++i) {
//        cerr << i << " " << int(s[0]) << " " << sz << endl;
		new_vert(i);
//        cerr << i << endl;
    }
//    cerr << "size = " << sz << endl;
    calc_depth(0, 0);

//    for (int i = 0; i <= 34; ++i)
//        cerr << "i == " << z[0].d[i] << endl;

    dfs(0, 0);

    for (int i = 0; i < min(s1.size(), min(s2.size(), s3.size())); ++i)
        cout << l[i] << " ";

	return 0;
}


#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <memory.h>
#include <algorithm>
#include <cassert>
#include <set>

using namespace std;

string s;

const int maxn = 2 * 1e6;

const int md = 1e9 + 7;

class suffixVert{
public:
	int l, r, suff, par, depth;
//	int g[30];
//    int d[30];
    map<int, int> g;
    map<int, int> d;
	inline int len() {
		return r - l;
	}
	suffixVert() {suff = -1, par = -1, l = 0, r = 0;/* memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));*/}
	suffixVert(int _l, int _r, int _par) {suff = -1, l = _l, r = _r, par = _par;/*memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));*/}
};

suffixVert z[maxn];
int sz, real_size;
int dyn[maxn][3];

void shrink() {
/*    cerr << "Here" << endl;
    exit(1);
//    double coeff = real_size > 1e5 ? 1.2 : 2;
    double coeff = 2;
    z = (suffixVert *) realloc(z, sizeof(suffixVert) * int(coeff * real_size));
//    for (int i = real_size; i < int(coeff * real_size); ++i)
//        z[i] = suffixVert();
    real_size = int(real_size * coeff);*/
}

inline int next(int v, char c)
{
    if (z[v].g.find((int)c) == z[v].g.end())
        return -1;
	return z[v].g[(int)c];
}

class state{
public:
	int v, pos;
	state() {v = 0, pos = 0;}
	state(int _v, int _pos) { v = _v, pos = _pos;}
};

state pos;

state findState(state st, int l, int r)
{
	while (l < r)
	{
//        assert(st.v >= 0 && st.v <= sz);
//        assert(l >= 0 && l < s.size());
//        assert(r >= 0 && r <= s.size());
		if (st.pos == z[st.v].len())
		{
			st.pos = 0;
			st.v = next(st.v, s[l]);
			if (st.v == -1)
            return st;
		} else {
			if (s[z[st.v].l + st.pos] != s[l])
				return state(-1, -1);
			if (r - l < z[st.v].len() - st.pos)
				return state(st.v, st.pos + r - l);
			l += z[st.v].len() - st.pos;
			st.pos = z[st.v].len();
		}
	}
	return st;
}

int cut_edge(state p)
{
//    cerr << p.v << endl;
//    assert(p.v >= 0 && p.v <= sz);
	if (p.pos == z[p.v].len())
		return p.v;
	if (p.pos == 0)
		return z[p.v].par;
	suffixVert tek = z[p.v];
	int last = sz++;
    if (last >= real_size) shrink();
//    assert(last >= 0 && last <= sz);
	z[last] = suffixVert(tek.l, tek.l + p.pos, tek.par);
//    assert(tek.l + p.pos >= 0 && tek.l + p.pos < s.size());
	z[last].g[(int)s[tek.l + p.pos]] = p.v;
//    assert(tek.par >= 0 && tek.par <= sz);
	z[tek.par].g[(int)s[tek.l]] = last;
//    assert(p.v >= 0 && p.v <= sz);
	z[p.v].par = last;
	z[p.v].l += p.pos;
	return last;
}

int make_link(int v)
{
  //  assert(v >= 0 && v <= sz);
	if (z[v].suff != -1)
		return z[v].suff;
	if (z[v].par == -1)
		return 0;
	int suff_par = make_link(z[v].par);
//    assert(suff_par >= 0 && suff_par <= sz);
//    assert(v >= 0 && v <= sz);
	state tek = findState(state(suff_par, z[suff_par].len()), z[v].l + (z[v].par == 0), z[v].r);
//    cerr << "v == " << v << endl;
    int tmp = cut_edge(tek);
//    cerr << "omg: " << tmp << endl;
	z[v].suff = tmp; // HERE PROBLEM
//    cerr << z[v].suff << endl;
	return z[v].suff;
}

void new_vert(int i)
{
	while(1)
	{
		state npos = findState(pos, i, i + 1);
		if (npos.v != -1)
		{
			pos = npos;
			return;
		}
		int p = cut_edge(pos);
		int last = sz++;
//        cerr << "last: " << last << endl;
        if (last >= real_size) shrink();
//        cerr << "last: " << last << " " << real_size << endl;
		z[last] = suffixVert(i, s.size(), p);
 //       cerr << "p: " << p << endl;
		z[p].g[(int)s[i]] = last;
//        cerr << "p2: " << p << endl;

		pos.v = make_link(p);
        if (pos.v == -1) pos.v = 0;
		pos.pos = z[pos.v].len();
		if (!p)
			break;
	}
}

int it = 0;

int l[maxn];

int calc_d(int l, int r, int c) {
    if (l == 0)
        return dyn[r - 1][c];
//    cerr << l << " " << r << " " << c << " " << dyn[r - 1][c] - dyn[l - 1][c] << endl;
    return dyn[r - 1][c] - dyn[l - 1][c];
}

void calc_depth(int v, int cur) {
    cur += z[v].len();
    z[v].depth = cur;

    for (map<int, int>::const_iterator it = z[v].g.begin(); it != z[v].g.end(); ++it) {
//    for (char c = 0; c <= 29; ++c) {
//    	if (next(v, c) != -1) {
//            int to = next(v, c);
            int to = it->second;
            char c = it->first;
    		calc_depth(to, cur);
/*            int tmp[3];
            tmp[0] = tmp[1] = tmp[2] = 0;
            for (int i = z[to].l; i < z[to].r; ++i)
                if ((int)s[i] <= 2)
                    tmp[s[i]] += 1;*/
            z[v].d[0] += calc_d(z[to].l, z[to].r, 0);
            z[v].d[1] += calc_d(z[to].l, z[to].r, 1);
            z[v].d[2] += calc_d(z[to].l, z[to].r, 2);
//            cerr << calc_d(z[to].l, z[to].r, 2) << " " << tmp[2] << endl;
            z[v].d[0] += z[to].d[0];
            z[v].d[1] += z[to].d[1];
            z[v].d[2] += z[to].d[2];
//            z[v].d[(int)c] += 1;
//            for (char c2 = 0; c2 <= 29; ++c2) {
//                z[v].d[(int)c2] += z[z[v].g[(int)c]].d[(int)c2];
//            }
        }
//    }
}

class node{
public:
    int l, r;
    long long value;
    node() {}
};

bool cmp(node a, node b) {
    if (a.l == b.l)
        return a.r < b.r;
    return a.l < b.l;
}

vector<node> ans;

void dfs(int v, int cur) {
//    for (int i = z[v].l; i < z[v].r; ++i) {
//        if (z[v].d[0] <= 2 || z[v].d[1] <= 1 || z[v].d[2] == 0)
//            continue;
//        cerr << v << char(s[i] - 4 + 'a') << " " << cur + i - z[v].l + 1 << " " << z[v].d[0] << " " << z[v].d[1] << " " << z[v].d[2] << endl;
        long long tmp1 = (z[v].d[0] - z[v].d[1]);
        long long tmp2 = (z[v].d[1] - z[v].d[2]);
        long long tmp3 = z[v].d[2];
//        cerr << cur + i - z[v].l << " " << tmp << " " << tmp2 << " " << tmp3 << endl;
        if (tmp1 > 0 && tmp2 > 0 && tmp3 > 0 && z[v].len() > 0) {
            node tmp;
            tmp.l = cur;
            tmp.r = cur + z[v].len();
            tmp.value = tmp1 * 1ll * tmp2 * 1ll * tmp3;
            ans.push_back(tmp);
//            l[cur + i - z[v].l] = (l[cur + i - z[v].l] + tmp * 1ll * tmp2 * 1ll * tmp3) % md;
        }
//       l[cur + i - z[v].l + 1] += (z[v].d[0] - z[v].d[1] - z) * (z[v].d[1] - 1) * (z[v].d[2] - 0);
//    }
    cur += z[v].len();

//    for (char c = 0; c <= 29; ++c)
    for (map<int, int>::const_iterator it = z[v].g.begin(); it != z[v].g.end(); ++it)
//        if (next(v, c) != -1)
//            dfs(next(v, c), cur);
        dfs(it->second, cur);
}

string s1, s2, s3;
int main()
{
    ios_base::sync_with_stdio(0);
    cin >> s1 >> s2 >> s3;

    int st_size = maxn;

    real_size = st_size;
//    z = (suffixVert *) malloc(sizeof(suffixVert) * real_size);
//    cerr << z << endl;
//    for (int i = 0; i < real_size; ++i)
//        z[i] = suffixVert();
    z[0] = suffixVert();

    for (int i = 0; i < s1.size(); ++i)
        s1[i] = s1[i] - 'a' + 3;
    for (int i = 0; i < s2.size(); ++i)
        s2[i] = s2[i] - 'a' + 3;
    for (int i = 0; i < s3.size(); ++i)
        s3[i] = s3[i] - 'a' + 3;

    s = s1;
    s.push_back(2);
    s += s2;
    s.push_back(1);
    s += s3;
    s.push_back(0);

    if (s[0] <= 2)
        dyn[0][s[0]] = 1;
    for (int i = 1; i < s.size(); ++i) {
        for (int j = 0; j <= 2; ++j)
            dyn[i][j] = dyn[i - 1][j];
        if (s[i] <= 2)
            dyn[i][s[i]]++;
    }
/*    for (int i = 0; i < s.size(); ++i)
        cerr << (int)s[i] << " ";
    cerr << endl;
    for (int i = 0; i < s.size(); ++i)
        cerr << dyn[i][0] << " " << dyn[i][1] << " " << dyn[i][2] << endl;*/

	sz = 1;

    cerr << s.size() << endl;

	for (int i = 0; i < s.size(); ++i) {
//        cerr << i << " " << int(s[0]) << " " << sz << endl;
		new_vert(i);
//        cerr << i << endl;
    }
    cerr << sz << endl;
    calc_depth(0, 0);

//    for (int i = 0; i <= 34; ++i)
//        cerr << "i == " << z[0].d[i] << endl;

    cerr << "size = " << sz << endl;
    dfs(0, 0);

    sort(ans.begin(), ans.end(), cmp);

//    for (int i = 0; i < ans.size(); ++i)
//        cerr << ans[i].l << " " << ans[i].r << " " << ans[i].value << endl;

    long long cur = 0;
    int p = 0;
    set<pair<int, long long> > z_s;
    for (int i = 0; i < min(s1.size(), min(s2.size(), s3.size())); ++i) {
        while (z_s.size() > 0 && z_s.begin()->first <= i) {
            cur -= z_s.begin()->second;
            z_s.erase(z_s.begin());
        }
        while (p < ans.size() && ans[p].l <= i) {
            cur += ans[p].value;
            z_s.insert(make_pair(ans[p].r, ans[p].value));
            ++p;
        }
        cout << cur % md << " ";
    }

//    for (int i = 0; i < min(s1.size(), min(s2.size(), s3.size())); ++i)
//        cout << l[i] << " ";

	return 0;
}


#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <memory.h>
#include <algorithm>
#include <cassert>

using namespace std;

string s;

const int maxn = 2 * 1e6;

class suffixVert{
public:
	int l, r, suff, par, depth;
	int g[30];
    int d[30];
	inline int len() {
		return r - l;
	}
	suffixVert() {suff = -1, par = -1, l = 0, r = 0; memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));}
	suffixVert(int _l, int _r, int _par) {suff = -1, l = _l, r = _r, par = _par; memset(g, -1, sizeof(g)); memset(d, 0, sizeof(d));}
};

suffixVert z[maxn];
int sz, real_size;

void shrink() {
/*    cerr << "Here" << endl;
    exit(1);
//    double coeff = real_size > 1e5 ? 1.2 : 2;
    double coeff = 2;
    z = (suffixVert *) realloc(z, sizeof(suffixVert) * int(coeff * real_size));
//    for (int i = real_size; i < int(coeff * real_size); ++i)
//        z[i] = suffixVert();
    real_size = int(real_size * coeff);*/
}

inline int next(int v, char c)
{
	return z[v].g[(int)c];
}

class state{
public:
	int v, pos;
	state() {v = 0, pos = 0;}
	state(int _v, int _pos) { v = _v, pos = _pos;}
};

state pos;

state findState(state st, int l, int r)
{
	while (l < r)
	{
//        assert(st.v >= 0 && st.v <= sz);
//        assert(l >= 0 && l < s.size());
//        assert(r >= 0 && r <= s.size());
		if (st.pos == z[st.v].len())
		{
			st.pos = 0;
			st.v = next(st.v, s[l]);
			if (st.v == -1)
            return st;
		} else {
			if (s[z[st.v].l + st.pos] != s[l])
				return state(-1, -1);
			if (r - l < z[st.v].len() - st.pos)
				return state(st.v, st.pos + r - l);
			l += z[st.v].len() - st.pos;
			st.pos = z[st.v].len();
		}
	}
	return st;
}

int cut_edge(state p)
{
//    cerr << p.v << endl;
//    assert(p.v >= 0 && p.v <= sz);
	if (p.pos == z[p.v].len())
		return p.v;
	if (p.pos == 0)
		return z[p.v].par;
	suffixVert tek = z[p.v];
	int last = sz++;
    if (last >= real_size) shrink();
//    assert(last >= 0 && last <= sz);
	z[last] = suffixVert(tek.l, tek.l + p.pos, tek.par);
//    assert(tek.l + p.pos >= 0 && tek.l + p.pos < s.size());
	z[last].g[(int)s[tek.l + p.pos]] = p.v;
//    assert(tek.par >= 0 && tek.par <= sz);
	z[tek.par].g[(int)s[tek.l]] = last;
//    assert(p.v >= 0 && p.v <= sz);
	z[p.v].par = last;
	z[p.v].l += p.pos;
	return last;
}

int make_link(int v)
{
  //  assert(v >= 0 && v <= sz);
	if (z[v].suff != -1)
		return z[v].suff;
	if (z[v].par == -1)
		return 0;
	int suff_par = make_link(z[v].par);
//    assert(suff_par >= 0 && suff_par <= sz);
//    assert(v >= 0 && v <= sz);
	state tek = findState(state(suff_par, z[suff_par].len()), z[v].l + (z[v].par == 0), z[v].r);
//    cerr << "v == " << v << endl;
    int tmp = cut_edge(tek);
//    cerr << "omg: " << tmp << endl;
	z[v].suff = tmp; // HERE PROBLEM
//    cerr << z[v].suff << endl;
	return z[v].suff;
}

void new_vert(int i)
{
	while(1)
	{
		state npos = findState(pos, i, i + 1);
		if (npos.v != -1)
		{
			pos = npos;
			return;
		}
		int p = cut_edge(pos);
		int last = sz++;
//        cerr << "last: " << last << endl;
        if (last >= real_size) shrink();
//        cerr << "last: " << last << " " << real_size << endl;
		z[last] = suffixVert(i, s.size(), p);
 //       cerr << "p: " << p << endl;
		z[p].g[(int)s[i]] = last;
//        cerr << "p2: " << p << endl;

		pos.v = make_link(p);
        if (pos.v == -1) pos.v = 0;
		pos.pos = z[pos.v].len();
		if (!p)
			break;
	}
}

int it = 0;

int l[maxn];

void calc_depth(int v, int cur) {
    cur += z[v].len();
    z[v].depth = cur;

    for (char c = 0; c <= 29; ++c) {
    	if (z[v].g[(int)c] != -1) {
    		calc_depth(z[v].g[(int)c], cur);
            for (int i = z[z[v].g[(int)c]].l; i < z[z[v].g[(int)c]].r; ++i)
                z[v].d[(int)s[i]] += 1;
            z[v].d[0] += z[z[v].g[(int)c]].d[0];
            z[v].d[1] += z[z[v].g[(int)c]].d[1];
            z[v].d[2] += z[z[v].g[(int)c]].d[2];
//            z[v].d[(int)c] += 1;
//            for (char c2 = 0; c2 <= 29; ++c2) {
//                z[v].d[(int)c2] += z[z[v].g[(int)c]].d[(int)c2];
//            }
        }
    }
}

void dfs(int v, int cur) {
    for (int i = z[v].l; i < z[v].r; ++i) {
//        if (z[v].d[0] <= 2 || z[v].d[1] <= 1 || z[v].d[2] == 0)
//            continue;
//        cerr << v << char(s[i] - 4 + 'a') << " " << cur + i - z[v].l + 1 << " " << z[v].d[0] << " " << z[v].d[1] << " " << z[v].d[2] << endl;
        long long tmp = (z[v].d[0] - z[v].d[1]);
        long long tmp2 = (z[v].d[1] - z[v].d[2]);
        long long tmp3 = z[v].d[2];
//        cerr << cur + i - z[v].l << " " << tmp << " " << tmp2 << " " << tmp3 << endl;
        if (tmp > 0 && tmp2 > 0 && tmp3 > 0) {
            l[cur + i - z[v].l] += tmp * tmp2 * tmp3;
        }
//       l[cur + i - z[v].l + 1] += (z[v].d[0] - z[v].d[1] - z) * (z[v].d[1] - 1) * (z[v].d[2] - 0);
    }
    cur += z[v].len();

    for (char c = 0; c <= 29; ++c)
        if (z[v].g[(int)c] != -1)
            dfs(z[v].g[(int)(c)], cur);
}

int main()
{
    ios_base::sync_with_stdio(0);
    string s1, s2, s3;
    cin >> s1 >> s2 >> s3;

    int st_size = maxn;

    real_size = st_size;
//    z = (suffixVert *) malloc(sizeof(suffixVert) * real_size);
//    cerr << z << endl;
//    for (int i = 0; i < real_size; ++i)
//        z[i] = suffixVert();
    z[0] = suffixVert();

    for (int i = 0; i < s1.size(); ++i)
        s1[i] = s1[i] - 'a' + 3;
    for (int i = 0; i < s2.size(); ++i)
        s2[i] = s2[i] - 'a' + 3;
    for (int i = 0; i < s3.size(); ++i)
        s3[i] = s3[i] - 'a' + 3;

    s = s1;
    s.push_back(2);
    s += s2;
    s.push_back(1);
    s += s3;
    s.push_back(0);

	sz = 1;

    cerr << s.size() << endl;

	for (int i = 0; i < s.size(); ++i) {
//        cerr << i << " " << int(s[0]) << " " << sz << endl;
		new_vert(i);
//        cerr << i << endl;
    }
    calc_depth(0, 0);

//    for (int i = 0; i <= 34; ++i)
//        cerr << "i == " << z[0].d[i] << endl;

    cerr << "size = " << sz << endl;
    dfs(0, 0);

    for (int i = 0; i < min(s1.size(), min(s2.size(), s3.size())); ++i)
        cout << l[i] << " ";

	return 0;
}


#include <iostream>
#include <ctime>
#include <string>
#include <cstring>
#include <cstdio>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <queue>
#include <algorithm>
#include <cassert>
#include <sstream>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
const int inf = 1e9;
const double eps = 1e-7;

const int maxn = 301000;
const ll mod = 1000000007;

struct node {
	int len, link;
	map<char, int> next;
	ll a1, a2, a3;
};

int sz = 1, last = 0;
node t[maxn * 2];

ll add[maxn];

void sa_extend(char c)
{
	int cur = sz++;
	t[cur].len = t[last].len + 1;
	int p;
	for (p = last; p != -1 && !t[p].next.count(c); p = t[p].link) {
		t[p].next[c] = cur;
	}
	if (p == -1) {
		t[cur].link = 0;
	} else {
		int q = t[p].next[c];
		if (t[p].len + 1 == t[q].len) {
			t[cur].link = q;
		} else {
			int clone = sz++;
			t[clone] = t[q];
			t[clone].len = t[p].len + 1;
			while (p != -1 && t[p].next[c] == q) {
				t[p].next[c] = clone;
				p = t[p].link;
			}
			t[cur].link = t[q].link = clone;
		}
	}

	last = cur;
}

int main()
{
#if 0
	freopen("in", "r", stdin);
	//freopen("out", "w", stdout);
#endif

	int n = 3;
	vector<string> s(n);
	t[0].link = -1;

	int minlen = maxn;
	for (int i = 0; i < n; ++i) {
		cin >> s[i];
		minlen = min(minlen, (int)s[i].size());
		for (int j = 0; j < (int)s[i].size(); ++j) {
			sa_extend(s[i][j]);
		}
		sa_extend('#');
	}
	for (int i = 0; i < n; ++i) {
		int v = 0;
		for (int j = 0; j < (int)s[i].size(); ++j) {
			char c = s[i][j];
			v = t[v].next[c];
			if (i == 0) t[v].a1++;
			else if (i == 1) t[v].a2++;
			else if (i == 2) t[v].a3++;
		}
	}
	vector<pii> a(sz);
	for (int i = 0; i < sz; ++i) {
		a[i] = pii(t[i].len, i);
	}
	sort(a.begin(), a.end());
	reverse(a.begin(), a.end());

	for (int i = 0; i < sz; ++i) {
		int id = a[i].second;
		int l = t[id].link;
		if (l != -1) {
			t[l].a1 += t[id].a1;
			t[l].a2 += t[id].a2;
			t[l].a3 += t[id].a3;
			ll p = (((t[id].a1 % mod) * (t[id].a2 % mod) % mod) * (t[id].a3 % mod)) % mod;
			add[t[l].len + 1] += p;
			add[t[id].len + 1] -= p;
		}
	}

	ll sum = 0;
	for (int i = 1; i <= minlen; ++i) {
		sum = (sum + add[i]) % mod;
		printf("%d ", (int)sum);
	}

	return 0;
}


#include <iostream>
#include <ctime>
#include <string>
#include <cstring>
#include <cstdio>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <queue>
#include <algorithm>
#include <cassert>
#include <sstream>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
const int inf = 1e9;
const double eps = 1e-7;

const int maxn = 301000;
const ll mod = 1000000007;

struct node {
	int len, link;
	map<char, int> next;
	ll a1, a2, a3;
};

int sz = 1, last = 0;
node t[maxn * 2];

ll add[maxn];

void sa_extend(char c)
{
	int cur = sz++;
	t[cur].len = t[last].len + 1;
	int p;
	for (p = last; p != -1 && !t[p].next.count(c); p = t[p].link) {
		t[p].next[c] = cur;
	}
	if (p == -1) {
		t[cur].link = 0;
	} else {
		int q = t[p].next[c];
		if (t[p].len + 1 == t[q].len) {
			t[cur].link = q;
		} else {
			int clone = sz++;
			t[clone] = t[q];
			t[clone].len = t[p].len + 1;
			while (p != -1 && t[p].next[c] == q) {
				t[p].next[c] = clone;
				p = t[p].link;
			}
			t[cur].link = t[q].link = clone;
		}
	}

	last = cur;
}

int main()
{
#if 0
	freopen("in", "r", stdin);
	//freopen("out", "w", stdout);
#endif

	int n = 3;
	vector<string> s(n);
	t[0].link = -1;

	int minlen = maxn;
	for (int i = 0; i < n; ++i) {
		cin >> s[i];
		minlen = min(minlen, (int)s[i].size());
		for (int j = 0; j < (int)s[i].size(); ++j) {
			sa_extend(s[i][j]);
		}
		sa_extend('#');
	}
	for (int i = 0; i < n; ++i) {
		int v = 0;
		for (int j = 0; j < (int)s[i].size(); ++j) {
			char c = s[i][j];
			v = t[v].next[c];
			if (i == 0) t[v].a1++;
			else if (i == 1) t[v].a2++;
			else if (i == 2) t[v].a3++;
		}
	}
	vector<pii> a(sz);
	for (int i = 0; i < sz; ++i) {
		a[i] = pii(t[i].len, i);
	}
	sort(a.begin(), a.end());
	reverse(a.begin(), a.end());

	for (int i = 0; i < sz; ++i) {
		int id = a[i].second;
		int l = t[id].link;
		if (l != -1) {
			t[l].a1 += t[id].a1;
			t[l].a2 += t[id].a2;
			t[l].a3 += t[id].a3;
			ll p = (((t[id].a1 % mod) * (t[id].a2 % mod) % mod) * (t[id].a3 % mod)) % mod;
			add[t[l].len + 1] += p;
			add[t[id].len + 1] -= p;
		}
	}

	ll sum = 0;
	for (int i = 1; i <= minlen; ++i) {
		sum = (sum + add[i]) % mod;
		sum = (sum + mod) % mod;
		printf("%d ", (int)sum);
	}

	return 0;
}


#include <iostream>
#include <ctime>
#include <string>
#include <cstring>
#include <cstdio>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <queue>
#include <algorithm>
#include <cassert>
#include <sstream>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
const int inf = 1e9;
const double eps = 1e-7;

const int maxn = 301000;
const ll mod = 1000000007;

struct node {
	int len, link;
	map<char, int> next;
	ll a1, a2, a3;
};

int sz = 1, last = 0;
node t[maxn * 2];

ll add[maxn];

void sa_extend(char c)
{
	int cur = sz++;
	t[cur].len = t[last].len + 1;
	int p;
	for (p = last; p != -1 && !t[p].next.count(c); p = t[p].link) {
		t[p].next[c] = cur;
	}
	if (p == -1) {
		t[cur].link = 0;
	} else {
		int q = t[p].next[c];
		if (t[p].len + 1 == t[q].len) {
			t[cur].link = q;
		} else {
			int clone = sz++;
			t[clone] = t[q];
			t[clone].len = t[p].len + 1;
			while (p != -1 && t[p].next[c] == q) {
				t[p].next[c] = clone;
				p = t[p].link;
			}
			t[cur].link = t[q].link = clone;
		}
	}

	last = cur;
}

int main()
{
#if 1
	freopen("in", "r", stdin);
	//freopen("out", "w", stdout);
#endif

	int n = 3;
	vector<string> s(n);
	t[0].link = -1;

	int minlen = maxn;
	for (int i = 0; i < n; ++i) {
		cin >> s[i];
		minlen = min(minlen, (int)s[i].size());
		for (int j = 0; j < (int)s[i].size(); ++j) {
			sa_extend(s[i][j]);
		}
		sa_extend('#');
	}
	for (int i = 0; i < n; ++i) {
		int v = 0;
		for (int j = 0; j < (int)s[i].size(); ++j) {
			char c = s[i][j];
			v = t[v].next[c];
			if (i == 0) t[v].a1++;
			else if (i == 1) t[v].a2++;
			else if (i == 2) t[v].a3++;
		}
	}
	vector<pii> a(sz);
	for (int i = 0; i < sz; ++i) {
		a[i] = pii(t[i].len, i);
	}
	sort(a.begin(), a.end());
	reverse(a.begin(), a.end());

	for (int i = 0; i < sz; ++i) {
		int id = a[i].second;
		int l = t[id].link;
		if (l != -1) {
			t[l].a1 += t[id].a1;
			t[l].a2 += t[id].a2;
			t[l].a3 += t[id].a3;
			ll p = (((t[id].a1 % mod) * (t[id].a2 % mod) % mod) * (t[id].a3 % mod)) % mod;
			add[t[l].len + 1] += p;
			add[t[id].len + 1] -= p;
		}
	}

	ll sum = 0;
	for (int i = 1; i <= minlen; ++i) {
		sum = (sum + add[i]) % mod;
		printf("%d ", (int)sum);
	}

	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define vi vector<int>
#define pii pair<int,int>
#define fr first
#define sc second
#define  LL   long long
#define inf 1<<29
#define mod 1000000007
#define LSOne(a) (a&(-a))
#define maxL  300010
inline bool cmp(const pii &p, const pii &q) { return (p.fr == q.fr)? p.sc > q.sc : p.fr > q.fr; }
struct state{
int len,link,cnt[4];
int next[27];
};
state st[maxL*2];
int last;
int sz,n;

char str1[maxL];
void ini_sa()
{
    sz=0;
    st[0].len=0;
    st[0].link=-1;
    for(int i=0;i<27;i++) st[0].next[i]=-1;
    ++sz;
}

void sa_insert(int c,int kk){

    int cur=sz++;
    st[cur].len=st[last].len+1;
    st[cur].cnt[kk]=1;
    for(int i=0;i<27;i++)        st[cur].next[i]=-1;
    int p;
    for(p=last;(p!=-1 ) &&  (st[p].next[c]==-1); p=st[p].link)
        st[p].next[c]=cur;
    if(p==-1)
        st[cur].link=0;
    else
    {
        int q=st[p].next[c];
        if(st[q].len  == (st[p].len+1))
          {
             st[cur].link=q;
          }
        else
        {
            int clone=sz++;
            st[clone].len=st[p].len+1;
            st[clone].cnt[kk]=0;
            memcpy(st[clone].next, st[q].next, sizeof st[clone].next);
            st[clone].link=st[q].link;
            int temp=clone;
            for(;(p!=-1) && (st[p].next[c]==q);p=st[p].link)
               {
                 st[p].next[c]=clone;
               }
            st[q].link=st[cur].link=clone;
        }
    }
    last=cur;
}

int b[maxL<<1];
pair<int,int> AA[maxL<<1];

int main()
{
    ini_sa();
    int p;
    int L=n;

     scanf("%s",str1);
    n=strlen(str1);
    L=n;
    for(int i=0;i<n;i++)
    {
        sa_insert(str1[i]-'a',0);
    }
    sa_insert(26,3);
     scanf("%s",str1);
    n=strlen(str1);
    L=min(L,n);
    for(int i=0;i<n;i++)
    {
        sa_insert(str1[i]-'a',1);
    }

    sa_insert(26,3);
     scanf("%s",str1);
    n=strlen(str1);
    L=min(n,L);
    for(int i=0;i<n;i++)
    {
        sa_insert(str1[i]-'a',2);
    }
    sa_insert(26,3);

    for(int i=0;i<sz;i++)
        AA[i]=make_pair(st[i].len,i);
    sort(AA,AA+sz,cmp);
    for(int i=0;i<sz;i++)
        b[i]=AA[i].sc;
    for(int i=0;i<sz-1;i++)
        if(b[i])
          {
           st[st[b[i]].link].cnt[0]+=st[b[i]].cnt[0];
           st[st[b[i]].link].cnt[1]+=st[b[i]].cnt[1];
           st[st[b[i]].link].cnt[2]+=st[b[i]].cnt[2];
          }
    LL a;
    LL ans[L+1];
    for(int i=0;i<=L;i++)
        ans[i]=0;
    for(int i=1;i<sz;i++)
    {
        a=st[i].cnt[0];
        a*=st[i].cnt[1];
        a%=mod;
        a*=st[i].cnt[2];
        a%=mod;
        if(!a) continue;
        ans[st[i].len]+=a;
        ans[st[i].len]%=mod;
        ans[st[st[i].link].len]+=(mod-a);
        ans[st[st[i].link].len]%=mod;
    }
    for(int i=L-1;i>=1;i--)
    {
             ans[i]+=ans[i+1];
            ans[i]%=mod;
    }
    for(int i=1;i<=L;i++)
        printf("%I64d ",ans[i]);
    printf("\n");
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define vi vector<int>
#define pii pair<int,int>
#define fr first
#define sc second
#define  LL   long long
#define inf 1<<29
#define mod 1000000007
#define LSOne(a) (a&(-a))
#define maxL  300010
inline bool cmp(const pii &p, const pii &q) { return (p.fr == q.fr)? p.sc > q.sc : p.fr > q.fr; }
struct state{
int len,link,cnt[4];
int next[27];
};
state st[maxL*2];
int last;
int sz,n;

char str1[maxL];
void ini_sa()
{
    sz=0;
    st[0].len=0;
    st[0].link=-1;
    for(int i=0;i<27;i++) st[0].next[i]=-1;
    ++sz;
}

void sa_insert(int c,int kk){

    int cur=sz++;
    st[cur].len=st[last].len+1;
    st[cur].cnt[kk]=1;
    for(int i=0;i<27;i++)        st[cur].next[i]=-1;
    int p;
    for(p=last;(p!=-1 ) &&  (st[p].next[c]==-1); p=st[p].link)
        st[p].next[c]=cur;
    if(p==-1)
        st[cur].link=0;
    else
    {
        int q=st[p].next[c];
        if(st[q].len  == (st[p].len+1))
          {
             st[cur].link=q;
          }
        else
        {
            int clone=sz++;
            st[clone].len=st[p].len+1;
            st[clone].cnt[kk]=0;
            memcpy(st[clone].next, st[q].next, sizeof st[clone].next);
            st[clone].link=st[q].link;
            int temp=clone;
            for(;(p!=-1) && (st[p].next[c]==q);p=st[p].link)
               {
                 st[p].next[c]=clone;
               }
            st[q].link=st[cur].link=clone;
        }
    }
    last=cur;
}

int b[maxL<<1];
pair<int,int> AA[maxL<<1];

int main()
{
    ini_sa();
    int p;
    int L=n;

     scanf("%s",str1);
    n=strlen(str1);
    L=n;
    for(int i=0;i<n;i++)
    {
        sa_insert(str1[i]-'a',0);
    }
    sa_insert(26,3);
     scanf("%s",str1);
    n=strlen(str1);
    L=min(L,n);
    for(int i=0;i<n;i++)
    {
        sa_insert(str1[i]-'a',1);
    }

    sa_insert(26,3);
     scanf("%s",str1);
    n=strlen(str1);
    L=min(n,L);
    for(int i=0;i<n;i++)
    {
        sa_insert(str1[i]-'a',2);
    }
    sa_insert(26,3);

    for(int i=0;i<sz;i++)
        AA[i]=make_pair(st[i].len,i);
    sort(AA,AA+sz,cmp);
    for(int i=0;i<sz;i++)
        b[i]=AA[i].sc;
    for(int i=0;i<sz-1;i++)
        if(b[i])
          {
           st[st[b[i]].link].cnt[0]+=st[b[i]].cnt[0];
           st[st[b[i]].link].cnt[1]+=st[b[i]].cnt[1];
           st[st[b[i]].link].cnt[2]+=st[b[i]].cnt[2];
          }
    LL a;
    LL ans[L+1];
    for(int i=0;i<=L;i++)
        ans[i]=0;
    for(int i=1;i<sz;i++)
    {
        a=st[i].cnt[0];
        a*=st[i].cnt[1];
        a%=mod;
        a*=st[i].cnt[2];
        if(!a) continue;
        ans[st[i].len]+=a;
        ans[st[i].len]%=mod;
        ans[st[st[i].link].len]+=(mod-a);
        ans[st[st[i].link].len]%=mod;
    }
    for(int i=L-1;i>=1;i--)
    {
             ans[i]+=ans[i+1];
            ans[i]%=mod;
    }
    for(int i=1;i<=L;i++)
        printf("%I64d ",ans[i]);
    printf("\n");
    return 0;
}


#include <algorithm>
#include <iostream>
#include <cassert>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <map>

using namespace std;

#define rofeach(i,x) for(type(x)i=x.rbegin();i!=x.rend();i++)
#define foreach(i,x) for(type(x)i=x.begin();i!=x.end();i++)
#define dbgs(x) cerr << (#x) << " --> " << (x) << ' '
#define dbg(x) cerr << (#x) << " --> " << (x) << endl
#define FOR(ii,aa,bb) for(int ii=aa;ii<=bb;ii++)
#define ROF(ii,aa,bb) for(int ii=aa;ii>=bb;ii--)
#define type(x) __typeof(x.begin())
#define pii pair< int,int >
#define mod 1000000007
#define inf 1000000000
#define ll long long
#define pb push_back
#define mp make_pair
#define nd second
#define st first
#define endl '\n'

const int N = 1e6+5;
const int logN = 20;
const int MAX = 1e9+5;

int lcp[N],suff[N],val[N][4],i,j,k,n,m,root[N],sorted[N],belong[N];

vector< pair< int , pii > > g;

pair< pii , int > C[N];

stack< int > S;

ll ans;

string str1,str2,str3,str;

int findset(int x){ return root[x] = root[x] == x ? x : findset(root[x]); }

int main(){

	cin >> str1 >> str2 >> str3;

	int s1 = str1.size();
	int s2 = str2.size();
	int s3 = str3.size();

	str = ' ' + str1 + '#' + str2 + '#' + str3;

	n = str.size()-1;

	int wh = 1;

	FOR(i,1,n) if(str[i] == '&' || str[i] == '#') wh++; else belong[i] = wh;

	FOR(i,1,n) suff[i] = str[i];

	FOR(j,1,logN){

		FOR(i,1,n) C[i] = mp(mp(suff[i],suff[min(i+(1<<j-1),n+1)]),i);

		sort(C+1,C+n+1);

		FOR(i,1,n) suff[C[i].nd] = suff[C[i-1].nd] + (C[i].st != C[i-1].st);

	}

	FOR(i,1,n) sorted[suff[i]] = i;

	int j = 0;

	FOR(i,1,n){

		if(suff[i] == 1) continue;

		while(i + j <= n && sorted[suff[i]-1]+j <= n && str[sorted[suff[i]-1]+j] == str[i+j]) j++;

		lcp[suff[i]] = j;

		if(j) j--;

	}

	FOR(i,1,n){

		root[i] = i;

		val[i][belong[i]] = 1;

		if(i > 1) g.pb(mp(lcp[i],mp(sorted[i-1],sorted[i])));

	}

	g.pb(mp(inf,mp(-1,-1)));

	sort(g.rbegin(),g.rend());

	int last = 1;

	int m = min(s1,min(s2,s3));

	ROF(i,m,1){

		while(last < n && g[last].st >= i){

			int x = findset(g[last].nd.st);
			int y = findset(g[last].nd.nd);

			last++;

			if(x == y) continue;

			root[y] = x;

			ans -= (ll)val[x][1] * val[x][2] * val[x][3] + (ll)val[y][1] * val[y][2] * val[y][3];

			val[x][1] += val[y][1];
			val[x][2] += val[y][2];
			val[x][3] += val[y][3];

			ans += (ll)val[x][1] * val[x][2] * val[x][3];

		}

		S.push(ans%mod);

	}

	while(!S.empty()){ cout << S.top() << ' '; S.pop(); }

    return 0;
}


#include <algorithm>
#include <iostream>
#include <cassert>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <map>

using namespace std;

#define rofeach(i,x) for(type(x)i=x.rbegin();i!=x.rend();i++)
#define foreach(i,x) for(type(x)i=x.begin();i!=x.end();i++)
#define dbgs(x) cerr << (#x) << " --> " << (x) << ' '
#define dbg(x) cerr << (#x) << " --> " << (x) << endl
#define FOR(ii,aa,bb) for(int ii=aa;ii<=bb;ii++)
#define ROF(ii,aa,bb) for(int ii=aa;ii>=bb;ii--)
#define type(x) __typeof(x.begin())
#define pii pair< int,int >
#define mod 1000000007
#define inf 1000000000
#define ll long long
#define pb push_back
#define mp make_pair
#define nd second
#define st first
#define endl '\n'

#define int ll

const int N = 1e6+5;
const int logN = 20;
const int MAX = 1e9+5;

int lcp[N],suff[N],val[N][4],i,j,k,n,m,root[N],sorted[N],belong[N];

vector< pair< int , pii > > g;

pair< pii , int > C[N];

stack< int > S;

ll ans;

string str1,str2,str3,str;

int findset(int x){ return root[x] = root[x] == x ? x : findset(root[x]); }

main(){

	cin >> str1 >> str2 >> str3;

	int s1 = str1.size();
	int s2 = str2.size();
	int s3 = str3.size();

	str = ' ' + str1 + '#' + str2 + '#' + str3;

	n = str.size()-1;

	int wh = 1;

	FOR(i,1,n) if(str[i] == '&' || str[i] == '#') wh++; else belong[i] = wh;

	FOR(i,1,n) suff[i] = str[i];

	FOR(j,1,logN){

		FOR(i,1,n) C[i] = mp(mp(suff[i],suff[min(i+(1<<j-1),n+1)]),i);

		sort(C+1,C+n+1);

		FOR(i,1,n) suff[C[i].nd] = suff[C[i-1].nd] + (C[i].st != C[i-1].st);

	}

	FOR(i,1,n) sorted[suff[i]] = i;

	int j = 0;

	FOR(i,1,n){

		if(suff[i] == 1) continue;

		while(i + j <= n && sorted[suff[i]-1]+j <= n && str[sorted[suff[i]-1]+j] == str[i+j]) j++;

		lcp[suff[i]] = j;

		if(j) j--;

	}

	FOR(i,1,n){

		root[i] = i;

		val[i][belong[i]] = 1;

		if(i > 1) g.pb(mp(lcp[i],mp(sorted[i-1],sorted[i])));

	}

	g.pb(mp(inf,mp(-1,-1)));

	sort(g.rbegin(),g.rend());

	int last = 1;

	int m = min(s1,min(s2,s3));

	ROF(i,m,1){

		while(last < n && g[last].st >= i){

			int x = findset(g[last].nd.st);
			int y = findset(g[last].nd.nd);

			last++;

			if(x == y) continue;

			root[y] = x;

			ans -= (ll)val[x][1] * val[x][2] * val[x][3] + (ll)val[y][1] * val[y][2] * val[y][3];

			FOR(i,1,3) val[x][i] += val[y][i];

			ans += (ll)val[x][1] * val[x][2] * val[x][3];

		}

		S.push(ans%mod);

	}

	while(!S.empty()){ cout << S.top() << ' '; S.pop(); }

    return 0;
}


#include <algorithm>
#include <iostream>
#include <cassert>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <cmath>
#include <ctime>
#include <queue>
#include <stack>
#include <map>

using namespace std;

#define rofeach(i,x) for(type(x)i=x.rbegin();i!=x.rend();i++)
#define foreach(i,x) for(type(x)i=x.begin();i!=x.end();i++)
#define dbgs(x) cerr << (#x) << " --> " << (x) << ' '
#define dbg(x) cerr << (#x) << " --> " << (x) << endl
#define FOR(ii,aa,bb) for(int ii=aa;ii<=bb;ii++)
#define ROF(ii,aa,bb) for(int ii=aa;ii>=bb;ii--)
#define type(x) __typeof(x.begin())
#define pii pair< int,int >
#define mod 1000000007
#define inf 1000000000
#define ll long long
#define pb push_back
#define mp make_pair
#define nd second
#define st first
#define endl '\n'

const int N = 1e6+5;
const int logN = 20;
const int MAX = 1e9+5;

int lcp[N],suff[N],val[N][4],i,j,k,n,m,root[N],sorted[N],belong[N];

vector< pair< int , pii > > g;

pair< pii , int > C[N];

stack< int > S;

ll ans;

string str1,str2,str3,str;

int findset(int x){ return root[x] = root[x] == x ? x : findset(root[x]); }

int main(){

	cin >> str1 >> str2 >> str3;

	int s1 = str1.size();
	int s2 = str2.size();
	int s3 = str3.size();

	str = ' ' + str1 + '#' + str2 + '#' + str3;

	n = str.size()-1;

	int wh = 1;

	FOR(i,1,n) if(str[i] == '&' || str[i] == '#') wh++; else belong[i] = wh;

	FOR(i,1,n) suff[i] = str[i];

	FOR(j,1,logN){

		FOR(i,1,n) C[i] = mp(mp(suff[i],suff[min(i+(1<<j-1),n+1)]),i);

		sort(C+1,C+n+1);

		FOR(i,1,n) suff[C[i].nd] = suff[C[i-1].nd] + (C[i].st != C[i-1].st);

	}

	FOR(i,1,n) sorted[suff[i]] = i;

	int j = 0;

	FOR(i,1,n){

		if(suff[i] == 1) continue;

		while(i + j <= n && sorted[suff[i]-1]+j <= n && str[sorted[suff[i]-1]+j] == str[i+j]) j++;

		lcp[suff[i]] = j;

		if(j) j--;

	}

	FOR(i,1,n){

		root[i] = i;

		val[i][belong[i]] = 1;

		if(i > 1) g.pb(mp(lcp[i],mp(sorted[i-1],sorted[i])));

	}

	g.pb(mp(inf,mp(-1,-1)));

	sort(g.rbegin(),g.rend());

	int last = 1;

	int m = min(s1,min(s2,s3));

	ROF(i,m,1){

		while(last < n && g[last].st >= i){

			int x = findset(g[last].nd.st);
			int y = findset(g[last].nd.nd);

			last++;

			if(x == y) continue;

			root[y] = x;

			ans -= (ll)val[x][1] * val[x][2] * val[x][3] + val[y][1] * val[y][2] * val[y][3];

			FOR(i,1,3) val[x][i] += val[y][i];

			ans += (ll)val[x][1] * val[x][2] * val[x][3];

			ans %= mod;

		}

		S.push(ans);

	}

	while(!S.empty()){ cout << S.top() << ' '; S.pop(); }

    return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<time.h>
#include<string>
#define cl(a,b)	memset(a,b,sizeof(a))
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define REP(i,n) for(int i=0;i<n;++i)
#define REP1(i,a,b) for(int i=a;i<=b;++i)
#define REP2(i,a,b) for(int i=a;i>=b;--i)
#define MP make_pair
#define LL long long
#define ULL unsigned long long
#define X first
#define Y second
#define MOD 1000000007
using namespace std;

const int MAXN = 300050;

struct SuffixArray {
	int wa[MAXN];
	int wb[MAXN];
	int wv[MAXN];
	int ws[MAXN];

	int sa[MAXN];
	int rank[MAXN];
	int height[MAXN];
	int r[MAXN];
	int n;
	int m;

	void input(int *val, int len, int Max) {
		for (int i = 0; i < len; i++)
			r[i] = val[i];
		r[len] = 0;
		n = len;
		m = Max;
		calSa();
		calHeight();
	}

	int cmp(int *r, int a, int b, int l) {
		return (r[a] == r[b] && r[a + l] == r[b + l]);
	}

	void calSa() {
		int i, j, p, *x = wa, *y = wb, *t;
		for (i = 0; i < m; i++)
			ws[i] = 0;
		for (i = 0; i < n + 1; i++)
			ws[x[i] = r[i]]++;
		for (i = 1; i < m; i++)
			ws[i] += ws[i - 1];
		for (i = n; i >= 0; i--)
			sa[--ws[x[i]]] = i;
		for (j = 1, p = 1; p < n + 1; j *= 2, m = p) {
			for (p = 0, i = n - j + 1; i < n + 1; i++)
				y[p++] = i;
			for (i = 0; i < n + 1; i++)
				if (sa[i] >= j)
					y[p++] = sa[i] - j;
			for (i = 0; i < n + 1; i++)
				wv[i] = x[y[i]];
			for (i = 0; i < m; i++)
				ws[i] = 0;
			for (i = 0; i < n + 1; i++)
				ws[wv[i]]++;
			for (i = 1; i < m; i++)
				ws[i] += ws[i - 1];
			for (i = n; i >= 0; i--)
				sa[--ws[wv[i]]] = y[i];
			for (t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n + 1;
					i++)
				x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++;
		}
	}

	void calHeight() {
		int i, j, k = 0;
		for (i = 1; i <= n; i++)
			rank[sa[i]] = i;
		for (i = 0; i < n; height[rank[i++]] = k)
			for (k ? k-- : 0, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; k++)
				;
	}

} SA;
char s1[MAXN], s2[MAXN], s3[MAXN];
int s[MAXN];
vector<int> e[MAXN];
int id[MAXN];
LL x[MAXN], y[MAXN], z[MAXN];
int fa[MAXN];
LL cnt[MAXN];
int getfa(int x) {
	if (fa[x] == x)
		return x;
	else
		return fa[x] = getfa(fa[x]);
}
LL mul(int a, int b, int c, int d) {
	return (((((a * b) % MOD) * c) % MOD) * d) % MOD;
}
int main() {
	int h = 0, len1, len2, len3;
	scanf(" %s %s %s", s1, s2, s3);
	len1 = strlen(s1);
	len2 = strlen(s2);
	len3 = strlen(s3);
	for (int i = 0; i < len1; ++i) {
		id[h] = 0;
		s[h++] = s1[i];
	}
	s[h++] = 1;
	for (int i = 0; i < len2; ++i) {
		id[h] = 1;
		s[h++] = s2[i];
	}
	s[h++] = 2;
	for (int i = 0; i < len3; ++i) {
		id[h] = 2;
		s[h++] = s3[i];
	}
	SA.input(s, h, 500);
//		for(int i=0;i<=h;++i)
//			printf("%d %d %d\n",i,SA.sa[i],SA.height[i]);
	for (int i = 0; i <= h; ++i)
		e[i].clear();
	for (int i = 1; i <= h; ++i) {
		e[SA.height[i]].push_back(i);
	}
	for (int i = 0; i <= h; ++i) {
		fa[i] = i;
		if (id[SA.sa[i]] == 0)
			x[i] = 1, y[i] = 0, z[i] = 0;
		else if (id[SA.sa[i]] == 1)
			x[i] = 0, y[i] = 1, z[i] = 0;
		else
			x[i] = 0, y[i] = 0, z[i] = 1;
	}
	LL pre = 0;
	LL ans = 0;
	for (int i = h; i > 0; --i) {
		cnt[i]=cnt[i+1];
		for (int j = 0; j < e[i].size(); ++j) {
			int u = e[i][j];
			int f1 = getfa(u);
			int f2 = getfa(u - 1);
//				printf("%d %d\n",f1,f2);
			if (f1 != f2) {
				ans -= mul(x[f2], y[f2], z[f2], i);
				ans -= mul(x[f1], y[f1], z[f1], i);
				fa[f1] = f2;
				x[f2] += x[f1];
				y[f2] += y[f1];
				z[f2] += z[f1];
				ans += mul(x[f2], y[f2], z[f2], 1);
				ans = (ans % MOD + MOD) % MOD;
//				printf("%d %I64d\n",i,ans);
			}
			cnt[i]+=ans-pre;
			cnt[i]=(cnt[i]%MOD+MOD)%MOD;
			pre=ans;
		}
	}
	int m = min(len1, len2);
	m = min(len3, m);
	for (int i = 1; i <= m; ++i) {
		printf("%I64d", cnt[i]);
		if (i == m)
			puts("");
		else
			printf(" ");
	}
}