//Three Strings
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<bits/stdc++.h>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<bitset>
#include<unordered_map>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define fio ios_base::sync_with_stdio(false)
#define mod 1000000007
#define mod1 mod
#define mod2 100000009
#define li long long int
#define ll li
// #define INT_MAX 5000000
#define readi(x) scanf("%d",&x)
#define  reads(x)  scanf("%s", x)
#define readl(x) scanf("%I64d",&x)
#define rep(i,n) for(i=0;i<n;i++)
#define revp(i,n) for(i=(n-1);i>=0;i--)
#define myrep1(i,a,b) for(i=a;i<=b;i++)
#define myrep2(i,a,b) for(i=b;i>=a;i--)
#define pb push_back
#define mp make_pair
#define fi first
#define sec second
#define si short int
#define INTMAX 1000000000
#define MAXN 1000000000000000
#define MINN -1000000000000000000
// #define INTMAX 1000001000
#define pii pair<ll,ll>
#define pdd pair<double,double>
#define pic pair<int,char>
#define N 2000000
#define lgn 20
#define ddouble long double
#define minus minu
#define PI 3.1415926535
#define lgn 20

// #define INTMAX 200000000
// using namespace boost;
// #define si short int

using namespace std;
using namespace __gnu_pbds;
typedef priority_queue<ll, vector<ll > ,greater<ll> > min_pq;
// typedef priority_queue<pii, vector<pii> , greater<pii >  > min_pq;
ll toint(const string &s) {stringstream ss; ss << s; ll x; ss >> x; return x;}
string tostring ( ll number ){stringstream ss; ss<< number; return ss.str();}

// using namespace __gnu_pbds;
// typedef priority_queue<pair<ll,char> , vector<pair<ll , char> > > max_pq;
// typedef priority_queue<pii , vector<pii > ,greater<pii > > min_pq;
typedef tree<pii , null_type, less<pii>, rb_tree_tag, tree_order_statistics_node_update> OST;
// typedef priority_queue<pair < ll , pair < pii , ll > >  , vector<pair < ll , pair < pii , ll > >  > ,greater<pair < ll , pair < pii , ll > >  > > min_pq;
#define TRACE
#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
    template <typename Arg1>
    void __f(const char* name, Arg1&& arg1){
        cout << name << " : " << arg1 << std::endl;
        //use cerr if u want to display at the bottom
    }
    template <typename Arg1, typename... Args>
    void __f(const char* names, Arg1&& arg1, Args&&... args){
        const char* comma = strchr(names + 1, ','); cout.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
    }
#else
#define trace(...)
#endif
// const int N=1000000,    // maximum possible number of nodes in suffix tree
const int INF=1000000000; // infinity constant
string a;       // input string for which the suffix tree is being built
li leafcost[N];
ll kitne[ N ][ 4 ];
ll lencost[N];
int t[N][29],   // array of transitions (state, letter)
    l[N],   // left...
    r[N],   // ...and right boundaries of the substring of a which correspond to incoming edge
    p[N],   // parent of the node
    s[N],   // suffix link
    tv,     // the node of the current suffix (if we're mid-edge, the lower node of the edge)
    tp,     // position in the string which corresponds to the position on the edge (between l[tv] and r[tv], inclusive)
    ts,     // the number of nodes
    la;     // the current character in the string

void ukkadd(int c) { // add character s to the tree
    suff:;      // we'll return here after each transition to the suffix (and will add character again)
    if (r[tv]<tp) { // check whether we're still within the boundaries of the current edge
        // if we're not, find the next edge. If it doesn't exist, create a leaf and add it to the tree
        if (t[tv][c]==-1) {t[tv][c]=ts;l[ts]=la;p[ts++]=tv;tv=s[tv];tp=r[tv]+1;goto suff;}
        tv=t[tv][c];tp=l[tv];
    } // otherwise just proceed to the next edge
    if (tp==-1 || c==a[tp]-'a')
        tp++; // if the letter on the edge equal c, go down that edge
    else {
        // otherwise split the edge in two with middle in node ts
        l[ts]=l[tv];r[ts]=tp-1;p[ts]=p[tv];t[ts][a[tp]-'a']=tv;
        // add leaf ts+1. It corresponds to transition through c.
        t[ts][c]=ts+1;l[ts+1]=la;p[ts+1]=ts;
        // update info for the current node - remember to mark ts as parent of tv
        l[tv]=tp;p[tv]=ts;t[p[ts]][a[l[ts]]-'a']=ts;ts+=2;
        // prepare for descent
        // tp will mark where are we in the current suffix
        tv=s[p[ts-2]];tp=l[ts-2];
        // while the current suffix is not over, descend
        while (tp<=r[ts-2]) {tv=t[tv][a[tp]-'a'];tp+=r[tv]-l[tv]+1;}
        // if we're in a node, add a suffix link to it, otherwise add the link to ts
        // (we'll create ts on next iteration).
        if (tp==r[ts-2]+1) s[ts-2]=tv; else s[ts-2]=ts;
        // add tp to the new edge and return to add letter to suffix
        tp=r[tv]-(tp-r[ts-2])+2;goto suff;
    }
}

void build() {
    ts=2;
    tv=0;
    tp=0;
    fill(r,r+N,(int)a.size()-1);
    // initialize data for the root of the tree
    s[0]=1;
    l[0]=-1;
    r[0]=-1;
    l[1]=-1;
    r[1]=-1;
    memset (t, -1, sizeof t);
    fill(t[1],t[1]+29,0);
    // add the text to the tree, letter by letter
    for (la=0; la<(int)a.size(); ++la)
        ukkadd (a[la]-'a');
}
set < ll > st;
ll c[ N ];
string tt[ 4 ];
ll pos[ 4 ];
li ans[ N ];
void dfs ( ll i , ll len, ll lenprev)
{
    ll lt = 0;
    for ( ll j = 0; j < 29; j ++)
    {
        if ( t[i][j] != -1 )
        {
            dfs(t[i][j],len + r[t[i][j]] - l[t[i][j]] + 1,len);
            for ( ll k = 1; k <=3; k ++)
                kitne[i][k] += kitne[t[i][j]][k];
        }
    }
    if ( r[i] == a.size()-1 )
    {
        kitne[i][lencost[len]] = 1;
    }
    ans[lenprev+1] += (kitne[i][1]*kitne[i][2]*kitne[i][3])%mod;
    ans[lenprev+1]%=mod;
    ans[len+1] += (mod-((kitne[i][1]*kitne[i][2]*kitne[i][3])%mod))%mod;
    ans[len+1]%=mod;
}
bool comp ( string a, string b )
{
    return a.size()>b.size();
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    #ifndef ONLINE_JUDGE
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    ll n;
    n = 3;
    ll len = 0;
    for ( ll i = 1; i <= n; i ++)
    {
        cin >> tt[i];
        len += (tt[i].size()) + 1;
    }
    sort(tt+1,tt+n+1,comp);
    for ( ll i = 1; i <= n; i ++){
        a += tt[i] + (char)('z'+i);
        pos[i] = (a.size()-1);
        for ( ll j = 0; j < tt[i].size(); j ++)
            lencost[len--] = i;
        lencost[len--] = 0;
    }
    // trace(a.size());
    lencost[len--] = 0;
    // for ( ll i = 0; i < a.size(); i ++)
    //     cout << lencost[i] <<" ";
    build();
    dfs(0,0,0);
    // dfs2(0,0,0);
    li pre = 0;
    for ( ll i = 1; i <= tt[3].size(); i ++)
    {
        pre = ( pre + ans[i])%mod;
        cout << pre <<" ";
    }
}


//Three Strings
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<bits/stdc++.h>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<bitset>
#include<unordered_map>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define fio ios_base::sync_with_stdio(false)
#define mod 1000000007
#define mod1 mod
#define mod2 100000009
#define li long long int
#define ll li
// #define INT_MAX 5000000
#define readi(x) scanf("%d",&x)
#define  reads(x)  scanf("%s", x)
#define readl(x) scanf("%I64d",&x)
#define rep(i,n) for(i=0;i<n;i++)
#define revp(i,n) for(i=(n-1);i>=0;i--)
#define myrep1(i,a,b) for(i=a;i<=b;i++)
#define myrep2(i,a,b) for(i=b;i>=a;i--)
#define pb push_back
#define mp make_pair
#define fi first
#define sec second
#define si short int
#define INTMAX 1000000000
#define MAXN 1000000000000000
#define MINN -1000000000000000000
// #define INTMAX 1000001000
#define pii pair<ll,ll>
#define pdd pair<double,double>
#define pic pair<int,char>
#define N 1000000
#define lgn 20
#define ddouble long double
#define minus minu
#define PI 3.1415926535
#define lgn 20

// #define INTMAX 200000000
// using namespace boost;
// #define si short int

using namespace std;
using namespace __gnu_pbds;
typedef priority_queue<ll, vector<ll > ,greater<ll> > min_pq;
// typedef priority_queue<pii, vector<pii> , greater<pii >  > min_pq;
ll toint(const string &s) {stringstream ss; ss << s; ll x; ss >> x; return x;}
string tostring ( ll number ){stringstream ss; ss<< number; return ss.str();}

// using namespace __gnu_pbds;
// typedef priority_queue<pair<ll,char> , vector<pair<ll , char> > > max_pq;
// typedef priority_queue<pii , vector<pii > ,greater<pii > > min_pq;
typedef tree<pii , null_type, less<pii>, rb_tree_tag, tree_order_statistics_node_update> OST;
// typedef priority_queue<pair < ll , pair < pii , ll > >  , vector<pair < ll , pair < pii , ll > >  > ,greater<pair < ll , pair < pii , ll > >  > > min_pq;
#define TRACE
#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
    template <typename Arg1>
    void __f(const char* name, Arg1&& arg1){
        cout << name << " : " << arg1 << std::endl;
        //use cerr if u want to display at the bottom
    }
    template <typename Arg1, typename... Args>
    void __f(const char* names, Arg1&& arg1, Args&&... args){
        const char* comma = strchr(names + 1, ','); cout.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
    }
#else
#define trace(...)
#endif
// const int N=1000000,    // maximum possible number of nodes in suffix tree
const int INF=1000000000; // infinity constant
string a;       // input string for which the suffix tree is being built
li leafcost[N];
ll kitne[ N ][ 4 ];
ll lencost[N];
int t[N][29],   // array of transitions (state, letter)
    l[N],   // left...
    r[N],   // ...and right boundaries of the substring of a which correspond to incoming edge
    p[N],   // parent of the node
    s[N],   // suffix link
    tv,     // the node of the current suffix (if we're mid-edge, the lower node of the edge)
    tp,     // position in the string which corresponds to the position on the edge (between l[tv] and r[tv], inclusive)
    ts,     // the number of nodes
    la;     // the current character in the string

void ukkadd(int c) { // add character s to the tree
    suff:;      // we'll return here after each transition to the suffix (and will add character again)
    if (r[tv]<tp) { // check whether we're still within the boundaries of the current edge
        // if we're not, find the next edge. If it doesn't exist, create a leaf and add it to the tree
        if (t[tv][c]==-1) {t[tv][c]=ts;l[ts]=la;p[ts++]=tv;tv=s[tv];tp=r[tv]+1;goto suff;}
        tv=t[tv][c];tp=l[tv];
    } // otherwise just proceed to the next edge
    if (tp==-1 || c==a[tp]-'a')
        tp++; // if the letter on the edge equal c, go down that edge
    else {
        // otherwise split the edge in two with middle in node ts
        l[ts]=l[tv];r[ts]=tp-1;p[ts]=p[tv];t[ts][a[tp]-'a']=tv;
        // add leaf ts+1. It corresponds to transition through c.
        t[ts][c]=ts+1;l[ts+1]=la;p[ts+1]=ts;
        // update info for the current node - remember to mark ts as parent of tv
        l[tv]=tp;p[tv]=ts;t[p[ts]][a[l[ts]]-'a']=ts;ts+=2;
        // prepare for descent
        // tp will mark where are we in the current suffix
        tv=s[p[ts-2]];tp=l[ts-2];
        // while the current suffix is not over, descend
        while (tp<=r[ts-2]) {tv=t[tv][a[tp]-'a'];tp+=r[tv]-l[tv]+1;}
        // if we're in a node, add a suffix link to it, otherwise add the link to ts
        // (we'll create ts on next iteration).
        if (tp==r[ts-2]+1) s[ts-2]=tv; else s[ts-2]=ts;
        // add tp to the new edge and return to add letter to suffix
        tp=r[tv]-(tp-r[ts-2])+2;goto suff;
    }
}

void build() {
    ts=2;
    tv=0;
    tp=0;
    fill(r,r+N,(int)a.size()-1);
    // initialize data for the root of the tree
    s[0]=1;
    l[0]=-1;
    r[0]=-1;
    l[1]=-1;
    r[1]=-1;
    memset (t, -1, sizeof t);
    fill(t[1],t[1]+29,0);
    // add the text to the tree, letter by letter
    for (la=0; la<(int)a.size(); ++la)
        ukkadd (a[la]-'a');
}
set < ll > st;
ll c[ N ];
string tt[ 4 ];
ll pos[ 4 ];
li ans[ N ];
void dfs ( ll i , ll len, ll lenprev)
{
    ll lt = 0;
    for ( ll j = 0; j < 29; j ++)
    {
        if ( t[i][j] != -1 )
        {
            dfs(t[i][j],len + r[t[i][j]] - l[t[i][j]] + 1,len);
            for ( ll k = 1; k <=3; k ++)
                kitne[i][k] += kitne[t[i][j]][k];
        }
    }
    if ( r[i] == a.size()-1 )
    {
        kitne[i][lencost[len]] = 1;
    }
    ans[lenprev+1] += (kitne[i][1]*kitne[i][2]*kitne[i][3])%mod;
    ans[lenprev+1]%=mod;
    ans[len+1] += (mod-((kitne[i][1]*kitne[i][2]*kitne[i][3])%mod))%mod;
    ans[len+1]%=mod;
}
bool comp ( string a, string b )
{
    return a.size()>b.size();
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    #ifndef ONLINE_JUDGE
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif
    ll n;
    n = 3;
    ll len = 0;
    for ( ll i = 1; i <= n; i ++)
    {
        cin >> tt[i];
        len += (tt[i].size()) + 1;
    }
    sort(tt+1,tt+n+1,comp);
    for ( ll i = 1; i <= n; i ++){
        a += tt[i] + (char)('z'+i);
        pos[i] = (a.size()-1);
        for ( ll j = 0; j < tt[i].size(); j ++)
            lencost[len--] = i;
        lencost[len--] = 0;
    }
    // trace(a.size());
    lencost[len--] = 0;
    // for ( ll i = 0; i < a.size(); i ++)
    //     cout << lencost[i] <<" ";
    build();
    dfs(0,0,0);
    // dfs2(0,0,0);
    li pre = 0;
    for ( ll i = 1; i <= tt[3].size(); i ++)
    {
        pre = ( pre + ans[i])%mod;
        cout << pre <<" ";
    }
}


//let's do it
 #include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define inf 1000000000000
#define mod 1000000007
#define pb push_back
#define mp make_pair
#define all(v) v.begin(),v.end()
#define S second
#define F first
#define boost1 ios::sync_with_stdio(false);
#define boost2 cin.tie(0);
#define mem(a,val) memset(a,val,sizeof a)
#define endl "\n"
#define maxn 350001

string S;
ll sa[maxn], pos[maxn], tmp[maxn], lcp[maxn], N, gap, freq[maxn],t[4*maxn];
ll par[maxn],cnt[maxn][4],ans[maxn],belong[maxn];
vector<ll>position[maxn];

ll find(ll x)
{
	if(par[x]==x)
	return x;
	return par[x]=find(par[x]);
}
ll add(ll x,ll y)
{
	return (x+y+mod)%mod;
}
ll mul(ll x,ll y)
{
	return (1LL*x*y)%mod;
}
ll sub(ll x,ll y)
{
	return (x-y+mod)%mod;
}
bool Sufcmp(int i, int j){
	if(pos[i] != pos[j]){
		return pos[i] < pos[j];
	}
	i += gap; j += gap;
	return (i < N && j < N) ? pos[i] < pos[j] : i > j;
}

void buildSA(){
	N = S.size();
	for(int i = 0; i < N; i++){
		sa[i] = i;
		pos[i] = S[i];
	}
	tmp[0] = 0;
	for(gap = 1; ; gap = (gap << 1)){
		sort(sa, sa + N, Sufcmp);
		for(int i = 0; i < N-1; i++) tmp[i+1] = tmp[i] + Sufcmp(sa[i], sa[i+1]);
		for(int i = 0; i < N; i++) pos[sa[i]] = tmp[i];
		if(tmp[N-1] == N-1) break;
	}
}

void buildLCP(){
	N = S.size();
	lcp[0] = 0;
	for(int i = 0, k = 0; i < N; i++){
		if(pos[i] != N-1){
			for(int j = sa[pos[i]+1]; S[i+k] == S[j+k]; )
				k++;
			lcp[pos[i]+1] = k;
			if(k) k--;
		}
	}
}
void merge(int x,int y,int len)
{
	ll xp=find(x);
	ll yp=find(y);
	if(xp==yp)
	return;
	ll temp=cnt[xp][1]+cnt[yp][1];
	temp=mul(temp,cnt[xp][2]+cnt[yp][2]);
	temp=mul(temp,cnt[xp][3]+cnt[yp][3]);
	temp=sub(temp,mul(cnt[xp][1],mul(cnt[xp][2],cnt[xp][3])));
	temp=sub(temp,mul(cnt[yp][1],mul(cnt[yp][2],cnt[yp][3])));
	ans[len]=add(ans[len],temp);
	par[xp]=yp;
	for(ll i=1;i<=3;i++)
	cnt[yp][i]+=cnt[xp][i];
}
int main()
{
	boost1;boost2;
	string s1,s2,s3;
	ll i,j,l1,l2,l3,x,y;
	cin>>s1>>s2>>s3;
	l1=s1.length();
	l2=s2.length();
	l3=s3.length();
	S=s1+'#'+s2+'$'+s3+'%';
	N=S.length();
	for(i=0;i<l1;i++)
	belong[i]=1;
	for(i=l1+1;i<=l1+l2;i++)
	belong[i]=2;
	for(i=l1+l2+2;i<N-1;i++)
	belong[i]=3;
	buildSA();
	buildLCP();
	for(i=0;i<N;i++)
	{
		par[i]=i;
		cnt[i][belong[sa[i]]]++;
	}
	for(i=0;i<N;i++)
	position[lcp[i]].pb(i);
	for(i=N;i>=1;i--)
	{
		for(auto it:position[i])
		{
			x=it;
			y=x-1;
			merge(x,y,i);
		}
	}
	for(i=N;i>=1;i--)
	ans[i]=add(ans[i],ans[i+1]);
	for(i=1;i<=min(l1,min(l2,l3));i++)
	cout<<ans[i]<<" ";
	return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int M = 600005;
const int MOD = 1e9+7;
int read()
{
    int x=0,flag=1;
    char c;
    while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
    while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
    return x*flag;
}
int n,m,k;char s[M];
struct edge
{
    int v,next;
    edge(int V=0,int N=0) : v(V) , next(N) {}
};
struct automaton
{
    int cnt,last,len[M],fa[M],ch[M][26],val[M][4];
    int tot,f[M],ans[M];edge e[2*M];
    automaton() {last=cnt=1;}
    void add(int c,int id)
    {
        int p=last,np=last=++cnt;
        val[np][id]=1;
        len[np]=len[p]+1;
        for(; p && !ch[p][c]; p=fa[p]) ch[p][c]=np;
        if(!p) fa[np]=1;
        else
        {
            int q=ch[p][c];
            if(len[q]==len[p]+1) fa[np]=q;
            else
            {
                int nq=++cnt;
                fa[nq]=fa[q];
                memcpy(ch[nq],ch[q],sizeof ch[q]);
                len[nq]=len[p]+1;
                fa[q]=fa[np]=nq;
                for(; p && ch[p][c]==q; p=fa[p]) ch[p][c]=nq;
            }
        }
    }
    void dfs(int u)
    {
        for(int i=f[u];i;i=e[i].next)
        {
            int v=e[i].v;
            if(v==fa[u]) continue;
            dfs(v);
            for(int j=1;j<=n;j++)
                val[u][j]+=val[v][j];
        }
    }
    void work()
    {
        for(int i=2;i<=cnt;i++)
        {
            int u=i,v=fa[i];
            e[++tot]=edge(v,f[u]),f[u]=tot;
            e[++tot]=edge(u,f[v]),f[v]=tot;
        }
        dfs(1);
        for(int i=2;i<=cnt;i++)
        {
            int c=1ll*val[i][1]*val[i][2]*val[i][3]%MOD;
            ans[len[fa[i]]+1]=(ans[len[fa[i]]+1]+c)%MOD;
            ans[len[i]+1]=(ans[len[i]+1]-c+MOD)%MOD;
        }
        for(int i=1;i<=k;i++)
            ans[i]=(ans[i]+ans[i-1])%MOD;
        for(int i=1;i<=k;i++)
            printf("%d ",ans[i]);
    }
}sam;
int main()
{
    n=3;k=5e5;
    for(int i=1;i<=n;i++)
    {
        sam.last=1;
        scanf("%s",s),m=strlen(s);
        k=min(k,m);
        for(int j=0;j<m;j++) sam.add(s[j]-'a',i);
    }
    sam.work();
}


#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn = 3e5+100;
ll sum[maxn*2];
/*注意需要按l将节点基数排序来拓扑更新parent树*/
struct Suffix_Automaton{
    //basic
    int nxt[maxn*2][26],fa[maxn*2],l[maxn*2];
    int last,cnt;
    //extension
    int cntA[maxn*2],A[maxn*2];/*辅助拓扑更新*/
    int num1[maxn*2],num2[maxn*2],num3[maxn*2];/*每个节点代表的所有串的出现次数*/
    int mask[maxn*2];
    Suffix_Automaton(){ clear(); }
    void clear(){
        last =cnt=1;
        fa[1]=l[1]=0;
        memset(nxt[1],0,sizeof nxt[1]);
    }
    void init(char *s){
        while (*s){
            add(*s-'a');s++;
        }
    }
    void add(int c){
        int p = last;
        int np = ++cnt;
        memset(nxt[cnt],0,sizeof nxt[cnt]);
        l[np] = l[p]+1;last = np;
        while (p&&!nxt[p][c])nxt[p][c] = np,p = fa[p];
        if (!p)fa[np]=1;
        else{
            int q = nxt[p][c];
            if (l[q]==l[p]+1)fa[np] =q;
            else{
                int nq = ++ cnt;
                l[nq] = l[p]+1;
                memcpy(nxt[nq],nxt[q],sizeof (nxt[q]));
                fa[nq] =fa[q];fa[np] = fa[q] =nq;
                while (nxt[p][c]==q)nxt[p][c] =nq,p = fa[p];
            }
        }
    }
    void build(){
        memset(cntA,0,sizeof cntA);
        memset(num1,0,sizeof num1);
        memset(num2,0,sizeof num2);
        memset(num3,0,sizeof num3);
        for (int i=1;i<=cnt;i++)cntA[l[i]]++;
        for (int i=1;i<=cnt;i++)cntA[i]+=cntA[i-1];
        for (int i=cnt;i>=1;i--)A[cntA[l[i]]--] =i;
    }

    void build(char s[],int len,int f){
        int now=1;
        int col=1<<(f-1);
        for(int i=0;i<len;i++){
            now=nxt[now][s[i]-'a'];
            mask[now]|=col;
            if(f==1)num1[now]++;
            else if(f==2)num2[now]++;
            else if(f==3)num3[now]++;
        }
    }
    void query(){
        for(int i=cnt;i>=1;i--){
            int x=A[i];
            mask[fa[x]]|=mask[x];
            num1[fa[x]]+=num1[x];
            num2[fa[x]]+=num2[x];
            num3[fa[x]]+=num3[x];
            if(mask[x]==7){
                ll ans=1ll*num1[x]*num2[x]%mod*num3[x]%mod;
                sum[l[x]+1]=(sum[l[x]+1]+mod-ans)%mod;
                sum[l[fa[x]]+1]=(sum[l[fa[x]]+1]+ans)%mod;
            }
        }
    }

    void debug(){
        for (int i=cnt;i>=1;i--){
            printf("num1[%d]=%d num2[%d]=%d num3[%d]=%d l[%d]=%d fa[%d]=%d\n",i,num1[i],i,num2[i],i,num3[i],i,l[i],i,fa[i]);
        }
    }
}sam;

char s1[maxn],s2[maxn],s3[maxn];
int len1,len2,len3;
int main(){
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif
    scanf("%s%s%s",s1,s2,s3);
    len1=strlen(s1);
    len2=strlen(s2);
    len3=strlen(s3);
    sam.init(s1);
    sam.last=1;
    sam.init(s2);
    sam.last=1;
    sam.init(s3);
    sam.build();
    sam.build(s1,len1,1);
    //sam.debug();
    sam.build(s2,len2,2);
    //sam.debug();
    sam.build(s3,len3,3);
    sam.query();
    //sam.debug();
    int len=min(len1,min(len2,len3));
    for(int i=1;i<=len;i++){
        sum[i]=(sum[i]+sum[i-1])%mod;
        printf("%lld ",sum[i]);
    }
    return 0;
}


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <bitset>
#include <map>
#include <vector>
#include <stack>
#include <set>
#include <cmath>
#ifdef LOCAL
#define debug(x) cout<<#x<<" = "<<(x)<<endl;
#else
#define debug(x) 1;
#endif

#define chmax(x,y) x=max(x,y)
#define chmin(x,y) x=min(x,y)
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
#define lowbit(x) x&-x
#define mp make_pair
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, int> pii;

const ll MOD = 1e9 + 7;
const double eps = 1e-10;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fll;
const int MAXN = 2e5 + 5;

const int maxn = 1e6 + 100;

struct SAM {
    // ch 转移函数, pre父亲, len最长长度, tag前缀标记, in入度, endnum endpos的个数 o 顺序
    int ch[maxn][27], pre[maxn], len[maxn], tag[maxn], in[maxn], endnum[maxn][3];
    int last, tot;
    void init() {
        last = tot = 0;
        memset (ch[0], -1, sizeof ch[0]);
        pre[0] = -1;
        len[0] = in[0] = 0;
    }
    // 加多个串时为了保证不跨串算
    void reset() {
        last = 0;
    }

    int extend (int c, int ind) {
        int p = last, np = ++tot;
        len[np] = len[p] + 1;
        endnum[np][ind]++;
        memset (ch[np], -1, sizeof ch[np]);
        in[np] = 0;

        while (~p && ch[p][c] == -1) ch[p][c] = np, p = pre[p];
        if (p == -1) {
            pre[np] = 0;
            in[0]++;
        } else {
            int q = ch[p][c];
            if (len[q] != len[p] + 1) {
                int nq = ++tot;
                memcpy (ch[nq], ch[q], sizeof ch[q]);
                in[nq] = tag[nq] = 0;
                len[nq] = len[p] + 1;
                pre[nq] = pre[q];
                pre[q] = pre[np] = nq;
                in[nq] += 2;
                while (~p && ch[p][c] == q) ch[p][c] = nq, p = pre[p];
            } else {
                pre[np] = q;
                in[q]++;
            }
        }
        last = np;
        return len[np] - len[pre[np]];
    }

    // 按照pre树计数排序  who为第i个位置的编号
    int who[maxn], a[maxn];
    void Sort() {
        for (int i = 1; i <= tot; i++) a[i] = 0;
        for (int i = 1; i <= tot; i++) a[len[i]]++;
        for (int i = 1; i <= tot; i++) a[i] += a[i - 1];
        for (int i = 1; i <= tot; i++) who[a[len[i]]--] = i;
        for (int i = tot; i >= 1; i--) {
            int u = who[i];
            if(u) for(int j = 0; j < 3; j++) endnum[pre[u]][j] += endnum[u][j];
        }
    }

    ll ans[maxn];

    void solve(int n) {
        for(int i = tot; i >= 1; i--) {
            int u = who[i];
            ll num = (ll)endnum[u][0] * endnum[u][1] % MOD * endnum[u][2] % MOD;
            (ans[len[pre[u]] + 1] += num) %= MOD;
            (ans[len[u] + 1] -= num += MOD) %= MOD;
        }
        for(int i = 1; i <= n; i++) {
            ans[i] = (ans[i] + ans[i - 1] + MOD) % MOD;
            printf("%lld ", ans[i]);
        }
    }

} sam;

char s[1000005];

int main() {
#ifdef LOCAL
    freopen ("input.txt", "r", stdin);
#endif
    sam.init();
    int minn = INF;
    for(int i = 0; i < 3; i++) {
        scanf("%s", s);
        minn = min(minn, (int)strlen(s));
        for(int j = 0; s[j]; j++) sam.extend(s[j] - 'a', i);
        sam.extend (26, 0);
    }
    sam.Sort();
    sam.solve(minn);

    return 0;
}


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <bitset>
#include <map>
#include <vector>
#include <stack>
#include <set>
#include <cmath>
#ifdef LOCAL
#define debug(x) cout<<#x<<" = "<<(x)<<endl;
#else
#define debug(x) 1;
#endif

#define chmax(x,y) x=max(x,y)
#define chmin(x,y) x=min(x,y)
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
#define lowbit(x) x&-x
#define mp make_pair
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, int> pii;

const ll MOD = 1e9 + 7;
const double eps = 1e-10;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fll;
const int MAXN = 2e5 + 5;

const int maxn = 1e6 + 100;

struct SAM {
    // ch 转移函数, pre父亲, len最长长度, tag前缀标记, in入度, endnum endpos的个数 o 顺序
    int ch[maxn][27], pre[maxn], len[maxn], tag[maxn], in[maxn], endnum[maxn][3];
    int last, tot;
    void init() {
        last = tot = 0;
        memset (ch[0], -1, sizeof ch[0]);
        pre[0] = -1;
        len[0] = in[0] = 0;
    }
    // 加多个串时为了保证不跨串算
    void reset() {
        last = 0;
    }

    int extend (int c, int ind) {
        int p = last, np = ++tot;
        len[np] = len[p] + 1;
        endnum[np][ind]++;
        memset (ch[np], -1, sizeof ch[np]);
        in[np] = 0;

        while (~p && ch[p][c] == -1) ch[p][c] = np, p = pre[p];
        if (p == -1) {
            pre[np] = 0;
            in[0]++;
        } else {
            int q = ch[p][c];
            if (len[q] != len[p] + 1) {
                int nq = ++tot;
                memcpy (ch[nq], ch[q], sizeof ch[q]);
                in[nq] = tag[nq] = 0;
                len[nq] = len[p] + 1;
                pre[nq] = pre[q];
                pre[q] = pre[np] = nq;
                in[nq] += 2;
                while (~p && ch[p][c] == q) ch[p][c] = nq, p = pre[p];
            } else {
                pre[np] = q;
                in[q]++;
            }
        }
        last = np;
        return len[np] - len[pre[np]];
    }

    // 按照pre树计数排序  who为第i个位置的编号
    int who[maxn], a[maxn];
    void Sort() {
        for (int i = 1; i <= tot; i++) a[i] = 0;
        for (int i = 1; i <= tot; i++) a[len[i]]++;
        for (int i = 1; i <= tot; i++) a[i] += a[i - 1];
        for (int i = 1; i <= tot; i++) who[a[len[i]]--] = i;
        for (int i = tot; i >= 1; i--) {
            int u = who[i];
            //if(tag[u]) endnum[u]++;
            if(u) for(int j = 0; j < 3; j++) endnum[pre[u]][j] += endnum[u][j];
        }
    }

    ll ans[maxn];

    void solve(int n) {
        for(int i = tot; i >= 1; i--) {
            int u = who[i];
            ll num = endnum[u][0] * endnum[u][1] % MOD * endnum[u][2] % MOD;
            (ans[len[pre[u]] + 1] += num) %= MOD;
            (ans[len[u] + 1] -= num += MOD) %= MOD;
        }
        for(int i = 1; i <= n; i++) {
            ans[i] = (ans[i] + ans[i - 1]) % MOD;
            printf("%lld ", ans[i]);
        }
    }

} sam;

char s[1000005];

int main() {
#ifdef LOCAL
    freopen ("input.txt", "r", stdin);
#endif
    sam.init();
    int minn = INF;
    for(int i = 0; i < 3; i++) {
        scanf("%s", s);
        minn = min(minn, (int)strlen(s));
        for(int j = 0; s[j]; j++) sam.extend(s[j] - 'a', i);
        sam.extend (26, 0);
    }
    sam.Sort();
    sam.solve(minn);

    return 0;
}


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <bitset>
#include <map>
#include <vector>
#include <stack>
#include <set>
#include <cmath>
#ifdef LOCAL
#define debug(x) cout<<#x<<" = "<<(x)<<endl;
#else
#define debug(x) 1;
#endif

#define chmax(x,y) x=max(x,y)
#define chmin(x,y) x=min(x,y)
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
#define lowbit(x) x&-x
#define mp make_pair
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, int> pii;

const ll MOD = 1e9 + 7;
const double eps = 1e-10;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fll;
const int MAXN = 2e5 + 5;

const int maxn = 1e6 + 100;

struct SAM {
    // ch 转移函数, pre父亲, len最长长度, tag前缀标记, in入度, endnum endpos的个数 o 顺序
    int ch[maxn][27], pre[maxn], len[maxn], tag[maxn], in[maxn], endnum[maxn][3];
    int last, tot;
    void init() {
        last = tot = 0;
        memset (ch[0], -1, sizeof ch[0]);
        pre[0] = -1;
        len[0] = in[0] = 0;
    }
    // 加多个串时为了保证不跨串算
    void reset() {
        last = 0;
    }

    int extend (int c, int ind) {
        int p = last, np = ++tot;
        len[np] = len[p] + 1;
        endnum[np][ind]++;
        memset (ch[np], -1, sizeof ch[np]);
        in[np] = 0;

        while (~p && ch[p][c] == -1) ch[p][c] = np, p = pre[p];
        if (p == -1) {
            pre[np] = 0;
            in[0]++;
        } else {
            int q = ch[p][c];
            if (len[q] != len[p] + 1) {
                int nq = ++tot;
                memcpy (ch[nq], ch[q], sizeof ch[q]);
                in[nq] = tag[nq] = 0;
                len[nq] = len[p] + 1;
                pre[nq] = pre[q];
                pre[q] = pre[np] = nq;
                in[nq] += 2;
                while (~p && ch[p][c] == q) ch[p][c] = nq, p = pre[p];
            } else {
                pre[np] = q;
                in[q]++;
            }
        }
        last = np;
        return len[np] - len[pre[np]];
    }

    // 按照pre树计数排序  who为第i个位置的编号
    int who[maxn], a[maxn];
    void Sort() {
        for (int i = 1; i <= tot; i++) a[i] = 0;
        for (int i = 1; i <= tot; i++) a[len[i]]++;
        for (int i = 1; i <= tot; i++) a[i] += a[i - 1];
        for (int i = 1; i <= tot; i++) who[a[len[i]]--] = i;
        for (int i = tot; i >= 1; i--) {
            int u = who[i];
            //if(tag[u]) endnum[u]++;
            if(u) for(int j = 0; j < 3; j++) endnum[pre[u]][j] += endnum[u][j];
        }
    }

    ll ans[maxn];

    void solve(int n) {
        for(int i = tot; i >= 1; i--) {
            int u = who[i];
            ll num = (ll)endnum[u][0] * endnum[u][1] % MOD * endnum[u][2] % MOD;
            (ans[len[pre[u]] + 1] += num) %= MOD;
            (ans[len[u] + 1] -= num += MOD) %= MOD;
        }
        for(int i = 1; i <= n; i++) {
            ans[i] = (ans[i] + ans[i - 1]) % MOD;
            printf("%lld ", ans[i]);
        }
    }

} sam;

char s[1000005];

int main() {
#ifdef LOCAL
    freopen ("input.txt", "r", stdin);
#endif
    sam.init();
    int minn = INF;
    for(int i = 0; i < 3; i++) {
        scanf("%s", s);
        minn = min(minn, (int)strlen(s));
        for(int j = 0; s[j]; j++) sam.extend(s[j] - 'a', i);
        sam.extend (26, 0);
    }
    sam.Sort();
    sam.solve(minn);

    return 0;
}


#include <bits/stdc++.h>
#define Pii pair<int,int>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define pb push_back
#define mem(W) memset(W,0,sizeof(W))
const int N = 3000007;
const int mod = 1e9 + 7;
using namespace std;
int n1,n2,n3;
char s1[N], s2[N], s3[N];
//cf452E
struct SAM {
    int n, step[N], fa[N], right[N][4], num[N], last, root, cnt;
    map<char,int> ch[N];
    char s[N];
    void init() {
        cnt = 0; last = root = ++ cnt;
    }
    void add(int x, int id) {
        int tmp = s[x],  p = last, np = ++cnt;
        step[last = np] = x, right[np][id] = 1;
        while(p && !ch[p][tmp]) ch[p][tmp] = np, p = fa[p];
        if(!p) fa[np] = root;
        else {
            int q = ch[p][tmp];
            if(step[q] == step[p] + 1) fa[np] = q;
            else {
                int nq = ++ cnt; step[nq] = step[p] + 1;
                //memcpy(ch[nq], ch[q], sizeof(ch[q]));
                ch[nq] = ch[q];
                fa[nq] = fa[q], fa[q] = fa[np] = nq;
                while(ch[p][tmp] == q) ch[p][tmp] = nq, p = fa[p];
            }
        }
    }
    int A[N];
    void calright() {
        memset(A, 0, sizeof(A));
        for(int i = 1; i <= cnt; ++i) ++ A[step[i]];
        for(int i = 1; i <= n; ++i) A[i] += A[i-1];
        for(int i = cnt; i; --i) num[A[step[i]]--] = i;
        for(int i = cnt; i; --i) {
            for(int j = 0; j < 3; ++j)
                right[fa[num[i]]][j] += right[num[i]][j];
        }
    }
    void run() {
        int i = 1;
        for( ; s[i] != '@'; ++i) add(i,0); add(i,3); ++ i;
        for( ; s[i] != '#'; ++i) add(i,1); add(i,3); ++ i;
        for( ; s[i] != '$'; ++i) add(i,2); add(i,3); ++ i;
        calright();
    }
} Fe;
long long ans[N];

int main() {
    scanf(" %s",s1+1), n1=strlen(s1+1);
    scanf(" %s",s2+1), n2=strlen(s2+1);
    scanf(" %s",s3+1), n3=strlen(s3+1);
    Fe.init();
    int cc =0;
    for(int i = 1; i <= n1; ++i) Fe.s[++cc] = s1[i]; Fe.s[++cc] = '@';
    for(int i = 1; i <= n2; ++i) Fe.s[++cc] = s2[i]; Fe.s[++cc] = '#';
    for(int i = 1; i <= n3; ++i) Fe.s[++cc] = s3[i]; Fe.s[++cc] = '$';
    Fe.n = cc;
    Fe.run();

    for(int i = 1; i <= Fe.last; ++i) {
        (ans[Fe.step[Fe.fa[i]]+1] += (Fe.right[i][0]*Fe.right[i][1]) % mod *Fe.right[i][2] % mod ) %= mod;
        (ans[Fe.step[i]+1] -= (Fe.right[i][0]*Fe.right[i][1]) % mod *Fe.right[i][2] % mod ) %= mod;
    }

    for(int i = 1; i <= min(n1,min(n2,n3)); ++ i) {
        (ans[i] += ans[i-1]) %= mod;
        (ans[i]+=mod)%=mod;
        cout << ans[i] <<' ';
    } puts("");
    return 0;
}


#include <bits/stdc++.h>
#define Pii pair<int,int>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define pb push_back
#define mem(W) memset(W,0,sizeof(W))
const int N = 3000007;
const int mod = 1e9 + 7;
using namespace std;
int n1,n2,n3;
char s1[N], s2[N], s3[N];
//cf452E
struct SAM {
    int n, step[N], fa[N], right[N][4], num[N], last, root, cnt;
    map<char,int> ch[N];
    char s[N];
    void init() {
        cnt = 0; last = root = ++ cnt;
    }
    void add(int x, int id) {
        int tmp = s[x],  p = last, np = ++cnt;
        step[last = np] = x, right[np][id] = 1;
        while(p && !ch[p][tmp]) ch[p][tmp] = np, p = fa[p];
        if(!p) fa[np] = root;
        else {
            int q = ch[p][tmp];
            if(step[q] == step[p] + 1) fa[np] = q;
            else {
                int nq = ++ cnt; step[nq] = step[p] + 1;
                //memcpy(ch[nq], ch[q], sizeof(ch[q]));
                ch[nq] = ch[q];
                fa[nq] = fa[q], fa[q] = fa[np] = nq;
                while(ch[p][tmp] == q) ch[p][tmp] = nq, p = fa[p];
            }
        }
    }
    int A[N];
    void calright() {
        memset(A, 0, sizeof(A));
        for(int i = 1; i <= cnt; ++i) ++ A[step[i]];
        for(int i = 1; i <= n; ++i) A[i] += A[i-1];
        for(int i = cnt; i; --i) num[A[step[i]]--] = i;
        for(int i = cnt; i; --i) {
            for(int j = 0; j < 3; ++j)
                right[fa[num[i]]][j] += right[num[i]][j];
        }
    }
    void run() {
        int i = 1;
        for( ; s[i] != '@'; ++i) add(i,0); add(i,3); ++ i;
        for( ; s[i] != '#'; ++i) add(i,1); add(i,3); ++ i;
        for( ; s[i] != '$'; ++i) add(i,2); add(i,3); ++ i;
        calright();
    }
} Fe;
long long ans[N];

int main() {
    scanf(" %s",s1+1), n1=strlen(s1+1);
    scanf(" %s",s2+1), n2=strlen(s2+1);
    scanf(" %s",s3+1), n3=strlen(s3+1);
    Fe.init();
    int cc =0;
    for(int i = 1; i <= n1; ++i) Fe.s[++cc] = s1[i]; Fe.s[++cc] = '@';
    for(int i = 1; i <= n2; ++i) Fe.s[++cc] = s2[i]; Fe.s[++cc] = '#';
    for(int i = 1; i <= n3; ++i) Fe.s[++cc] = s3[i]; Fe.s[++cc] = '$';
    Fe.n = cc;
    Fe.run();

    for(int i = 1; i <= Fe.last; ++i) {
        (ans[Fe.step[Fe.fa[i]]+1] += (1ll * Fe.right[i][0]*Fe.right[i][1]) % mod *Fe.right[i][2] % mod ) %= mod;
        (ans[Fe.step[i]+1] -= (1ll * Fe.right[i][0]*Fe.right[i][1]) % mod *Fe.right[i][2] % mod ) %= mod;
    }

    for(int i = 1; i <= min(n1,min(n2,n3)); ++ i) {
        (ans[i] += ans[i-1]) %= mod;
        (ans[i]+=mod)%=mod;
        cout << ans[i] <<' ';
    } puts("");
    return 0;
}


/*
PROG: cf452e
LANG: C++11
    _____
  .'     '.
 /  0   0  \
|     ^     |
|  \     /  |
 \  '---'  /
  '._____.'
 */
#include <bits/stdc++.h>

using namespace std;

long long readi()
{
	long long input = 0;
	char c = ' ';
	while (c < '-')
	{
		c = getchar();
	}
	bool negative = false;
	if (c == '-')
	{
		negative = true;
		c = getchar();
	}
	while (c >= '0')
	{
		input = 10 * input + (c - '0');
		c = getchar();
	}
	if (negative)
	{
		input = -input;
	}
	return input;
}
void printi(long long output)
{
	if (output == 0)
	{
		putchar('0');
		return;
	}
	if (output < 0)
	{
		putchar('-');
		output = -output;
	}
	int aout[20];
	int ilen = 0;
	while(output)
	{
		aout[ilen] = ((output % 10));
		output /= 10;
		ilen++;
	}
	for (int i = ilen - 1; i >= 0; i--)
	{
		putchar(aout[i] + '0');
	}
	return;
}
string reads()
{
	string input = "";
	char c = ' ';
	while (c <= ' ')
	{
		c = getchar();
	}
	while (c > ' ')
	{
		input += c;
		c = getchar();
	}
	return input;
}
int sgn(long long x)
{
	if (x < 0)
	{
		return -1;
	}
	if (x > 0)
	{
		return 1;
	}
	return 0;
}
long long randomize(long long x)
{
	return (((1ll << 31) * rand()) + rand()) % x;
}

#define MP make_pair
#define PB push_back
#define PF push_front
#define LB lower_bound
#define UB upper_bound
#define fi first
#define se second

const long double PI = 4.0 * atan(1.0);
const long double EPS = 1e-30;

#define SINF 10007
#define CO 1000007
#define INF 1000000007
#define BIG 1000000931
#define LARGE 1696969696967ll
#define GIANT 2564008813937411ll
#define LLINF 2696969696969696969ll
#define MAXN 300010
#define LOG 21

long long normalize(long long x, long long mod)
{
	return (((x % mod) + mod) % mod);
}

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

string temp;
int N, M, K, S;
int A[MAXN], B[MAXN], C[MAXN];
ll pref[MAXN][4], ans[MAXN];
int id[MAXN];
vector<int> v[MAXN];
int dsu[MAXN];
int L[MAXN], R[MAXN];
ll res;

struct suffixarray
{
	vector<int> s;
	int best;
	int sval[LOG + 2][MAXN];
	int suf[MAXN], srank[MAXN], lcp[MAXN];
	vector<int> sfi[MAXN], sse[MAXN];
	void getsuf()
	{
		for (int i = 0; i < s.size(); i++)
		{
			sval[0][i] = s[i];
		}
		for (int i = 0; i < LOG; i++)
		{
			int Z = max((int) s.size(), 256);
			for (int j = 0; j <= Z; j++)
			{
				sse[j].clear();
				sfi[j].clear();
			}
			for (int j = 0; j < s.size(); j++)
			{
				sse[sval[i][j + (1 << i)]].PB(j);
			}
			for (int j = 0; j <= Z; j++)
			{
				for (int k = 0; k < sse[j].size(); k++)
				{
					int idx = sse[j][k];
					sfi[sval[i][idx]].PB(idx);
				}
			}
			int cnt = 0;
			pii was = MP(-1, -1);
			for (int j = 0; j <= Z; j++)
			{
				for (int k = 0; k < sfi[j].size(); k++)
				{
					int idx = sfi[j][k];
					pii curp = MP(sval[i][idx], sval[i][idx + (1 << i)]);
					if (curp != was)
					{
						cnt++;
						was = curp;
					}
					sval[i + 1][idx] = cnt;
				}
			}
		}
		for (int i = 0; i < s.size(); i++)
		{
			srank[i] = sval[LOG][i] - 1;
			suf[srank[i]] = i;
		}
	}
	void getlcp()
	{
		for (int i = 0; i < s.size(); i++)
		{
			if (srank[i] == s.size() - 1)
			{
				best = 0;
				continue;
			}
			int idx = suf[srank[i] + 1];
			while(i + best < s.size() && idx + best < s.size() && s[i + best] == s[idx + best])
			{
				best++;
			}
			lcp[srank[i]] = best;
			best--;
			best = max(0, best);
		}
	}
};

suffixarray sfx;

ll solve(int L, int R)
{
	R++;
	ll ca = pref[R + 1][0] - pref[L][0];
	ll cb = pref[R + 1][1] - pref[L][1];
	ll cc = pref[R + 1][2] - pref[L][2];
	return (ca * cb * cc);
}

int32_t main()
{
	ios_base::sync_with_stdio(0);
	srand(time(0));
	//	cout << fixed << setprecision(12);
	//	cerr << fixed << setprecision(12);
	if (fopen("cf452e.in", "r"))
	{
		freopen ("cf452e.in", "r", stdin);
		freopen ("cf452e.out", "w", stdout);
	}
	cin >> temp;
	N = temp.length();
	for (int i = 0; i < N; i++)
	{
		A[i] = temp[i] - 'a' + 1;
	}
	cin >> temp;
	M = temp.length();
	for (int i = 0; i < M; i++)
	{
		B[i] = temp[i] - 'a' + 1;
	}
	cin >> temp;
	K = temp.length();
	for (int i = 0; i < K; i++)
	{
		C[i] = temp[i] - 'a' + 1;
	}
	S = min(N, min(M, K));
	for (int i = 0; i < N; i++)
	{
		sfx.s.PB(A[i]);
		id[sfx.s.size() - 1] = 0;
	}
	sfx.s.PB(27);
	id[sfx.s.size() - 1] = 3;
	for (int i = 0; i < M; i++)
	{
		sfx.s.PB(B[i]);
		id[sfx.s.size() - 1] = 1;
	}
	sfx.s.PB(28);
	id[sfx.s.size() - 1] = 3;
	for (int i = 0; i < K; i++)
	{
		sfx.s.PB(C[i]);
		id[sfx.s.size() - 1] = 2;
	}
	sfx.getsuf();
	sfx.getlcp();
//	for (int i = 0; i < sfx.s.size(); i++)
//	{
//		cerr << i % 10 << ' ';
//	}
//	cerr << endl;
//	for (int i = 0; i < sfx.s.size(); i++)
//	{
//		cerr << (char) ('a' + sfx.s[i] - 1) << ' ';
//	}
//	cerr << endl;
//	for (int i = 0; i < sfx.s.size(); i++)
//	{
//		cerr << sfx.suf[i] << ' ';
//	}
//	cerr << endl;
	for (int i = 0; i < sfx.s.size(); i++)
	{
		for (int j = 0; j < 3; j++)
		{
			pref[i + 1][j] = pref[i][j];
		}
		pref[i + 1][id[sfx.suf[i]]]++;
//		cerr << id[sfx.suf[i]] << ' ';
	}
//	cerr << endl;
	for (int i = 0; i < sfx.s.size() - 1; i++)
	{
		v[sfx.lcp[i]].PB(i);
//				cerr << sfx.lcp[i] << ' ';
	}
//		cerr << endl;
	for (int i = 0; i <= sfx.s.size() + 2; i++)
	{
		L[i] = -1;
		R[i] = -1;
	}
	for (int i = sfx.s.size(); i > 0; i--)
	{
		for (int idx : v[i])
		{
//			cerr << idx << ' ';
			if (idx != 0 && L[idx - 1] != -1)
			{
				if (R[idx + 1] != -1)
				{
					res += solve(L[idx - 1], R[idx + 1]);
					res -= solve(L[idx - 1], idx - 1);
					res -= solve(idx + 1, R[idx + 1]);
					R[L[idx - 1]] = R[idx + 1];
					L[R[idx + 1]] = L[idx - 1];
				}
				else
				{
					res += solve(L[idx - 1], idx);
					res -= solve(L[idx - 1], idx - 1);
					L[idx] = L[idx - 1];
					R[L[idx]] = idx;
				}
			}
			else
			{
				if (R[idx + 1] != -1)
				{
					res += solve(idx, R[idx + 1]);
					res -= solve(idx + 1, R[idx + 1]);
					R[idx] = R[idx + 1];
					L[R[idx]] = idx;
				}
				else
				{
					res += solve(idx, idx);
					L[idx] = idx;
					R[idx] = idx;
				}
			}
		}
//		cerr << endl;
		ans[i] = res % INF;
	}
	//0, 1, 3, 4, 5, 6, 10, 11, 12, 21, 22, 23
//	cerr << solve(0, 1) << ' ' << solve(3, 6) << ' ' << solve(10, 12) << ' ' << solve(21, 23) << endl;
	for (int i = 1; i <= S; i++)
	{
		cout << ans[i] << ' ';
	}
	cout << '\n';
	return 0;
}


/*
PROG: cf452e
LANG: C++11
    _____
  .'     '.
 /  0   0  \
|     ^     |
|  \     /  |
 \  '---'  /
  '._____.'
 */
#include <bits/stdc++.h>

using namespace std;

long long readi()
{
	long long input = 0;
	char c = ' ';
	while (c < '-')
	{
		c = getchar();
	}
	bool negative = false;
	if (c == '-')
	{
		negative = true;
		c = getchar();
	}
	while (c >= '0')
	{
		input = 10 * input + (c - '0');
		c = getchar();
	}
	if (negative)
	{
		input = -input;
	}
	return input;
}
void printi(long long output)
{
	if (output == 0)
	{
		putchar('0');
		return;
	}
	if (output < 0)
	{
		putchar('-');
		output = -output;
	}
	int aout[20];
	int ilen = 0;
	while(output)
	{
		aout[ilen] = ((output % 10));
		output /= 10;
		ilen++;
	}
	for (int i = ilen - 1; i >= 0; i--)
	{
		putchar(aout[i] + '0');
	}
	return;
}
string reads()
{
	string input = "";
	char c = ' ';
	while (c <= ' ')
	{
		c = getchar();
	}
	while (c > ' ')
	{
		input += c;
		c = getchar();
	}
	return input;
}
int sgn(long long x)
{
	if (x < 0)
	{
		return -1;
	}
	if (x > 0)
	{
		return 1;
	}
	return 0;
}
long long randomize(long long x)
{
	return (((1ll << 31) * rand()) + rand()) % x;
}

#define MP make_pair
#define PB push_back
#define PF push_front
#define LB lower_bound
#define UB upper_bound
#define fi first
#define se second

const long double PI = 4.0 * atan(1.0);
const long double EPS = 1e-30;

#define SINF 10007
#define CO 1000007
#define INF 1000000007
#define BIG 1000000931
#define LARGE 1696969696967ll
#define GIANT 2564008813937411ll
#define LLINF 2696969696969696969ll
#define MAXN 300010
#define LOG 21

long long normalize(long long x, long long mod)
{
	return (((x % mod) + mod) % mod);
}

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

string temp;
int N, M, K, S;
int A[MAXN], B[MAXN], C[MAXN];
ll pref[MAXN][4], ans[MAXN];
int id[MAXN];
vector<int> v[MAXN];
int dsu[MAXN];
int L[MAXN], R[MAXN];
ll res;

struct suffixarray
{
	vector<int> s;
	int best;
	int sval[LOG + 2][MAXN];
	int suf[MAXN], srank[MAXN], lcp[MAXN];
	vector<int> sfi[MAXN], sse[MAXN];
	void getsuf()
	{
		for (int i = 0; i < s.size(); i++)
		{
			sval[0][i] = s[i];
		}
		for (int i = 0; i < LOG; i++)
		{
			int Z = max((int) s.size(), 256);
			for (int j = 0; j <= Z; j++)
			{
				sse[j].clear();
				sfi[j].clear();
			}
			for (int j = 0; j < s.size(); j++)
			{
				sse[sval[i][j + (1 << i)]].PB(j);
			}
			for (int j = 0; j <= Z; j++)
			{
				for (int k = 0; k < sse[j].size(); k++)
				{
					int idx = sse[j][k];
					sfi[sval[i][idx]].PB(idx);
				}
			}
			int cnt = 0;
			pii was = MP(-1, -1);
			for (int j = 0; j <= Z; j++)
			{
				for (int k = 0; k < sfi[j].size(); k++)
				{
					int idx = sfi[j][k];
					pii curp = MP(sval[i][idx], sval[i][idx + (1 << i)]);
					if (curp != was)
					{
						cnt++;
						was = curp;
					}
					sval[i + 1][idx] = cnt;
				}
			}
		}
		for (int i = 0; i < s.size(); i++)
		{
			srank[i] = sval[LOG][i] - 1;
			suf[srank[i]] = i;
		}
	}
	void getlcp()
	{
		for (int i = 0; i < s.size(); i++)
		{
			if (srank[i] == s.size() - 1)
			{
				best = 0;
				continue;
			}
			int idx = suf[srank[i] + 1];
			while(i + best < s.size() && idx + best < s.size() && s[i + best] == s[idx + best])
			{
				best++;
			}
			lcp[srank[i]] = best;
			best--;
			best = max(0, best);
		}
	}
};

suffixarray sfx;

ll solve(int L, int R)
{
	R++;
	ll ca = pref[R + 1][0] - pref[L][0];
	ll cb = pref[R + 1][1] - pref[L][1];
	ll cc = pref[R + 1][2] - pref[L][2];
	return (ca * cb * cc);
}

int32_t main()
{
	ios_base::sync_with_stdio(0);
	srand(time(0));
	//	cout << fixed << setprecision(12);
	//	cerr << fixed << setprecision(12);
	if (fopen("cf452e.in", "r"))
	{
		freopen ("cf452e.in", "r", stdin);
		freopen ("cf452e.out", "w", stdout);
	}
	cin >> temp;
	N = temp.length();
	for (int i = 0; i < N; i++)
	{
		A[i] = temp[i] - 'a' + 1;
	}
	cin >> temp;
	M = temp.length();
	for (int i = 0; i < M; i++)
	{
		B[i] = temp[i] - 'a' + 1;
	}
	cin >> temp;
	K = temp.length();
	for (int i = 0; i < K; i++)
	{
		C[i] = temp[i] - 'a' + 1;
	}
	S = min(N, min(M, K));
	for (int i = 0; i < N; i++)
	{
		sfx.s.PB(A[i]);
		id[sfx.s.size() - 1] = 0;
	}
	sfx.s.PB(27);
	id[sfx.s.size() - 1] = 3;
	for (int i = 0; i < M; i++)
	{
		sfx.s.PB(B[i]);
		id[sfx.s.size() - 1] = 1;
	}
	sfx.s.PB(28);
	id[sfx.s.size() - 1] = 3;
	for (int i = 0; i < K; i++)
	{
		sfx.s.PB(C[i]);
		id[sfx.s.size() - 1] = 2;
	}
	sfx.getsuf();
	sfx.getlcp();
	for (int i = 0; i < sfx.s.size(); i++)
	{
		cerr << i % 10 << ' ';
	}
	cerr << endl;
	for (int i = 0; i < sfx.s.size(); i++)
	{
		cerr << sfx.s[i] << ' ';
	}
	cerr << endl;
	for (int i = 0; i < sfx.s.size(); i++)
	{
		cerr << id[sfx.suf[i]] << ' ';
	}
	cerr << endl;
	for (int i = 0; i < sfx.s.size(); i++)
	{
		for (int j = 0; j < 3; j++)
		{
			pref[i + 1][j] = pref[i][j];
		}
		pref[i + 1][id[sfx.suf[i]]]++;
		cerr << id[sfx.suf[i]] << ' ';
	}
	cerr << endl;
	for (int i = 0; i < sfx.s.size() - 1; i++)
	{
		v[sfx.lcp[i]].PB(i);
		//		cerr << sfx.lcp[i] << ' ';
	}
	//	cerr << endl;
	for (int i = 0; i <= sfx.s.size() + 2; i++)
	{
		L[i] = -1;
		R[i] = -1;
	}
	for (int i = S; i > 0; i--)
	{
		for (int idx : v[i])
		{
			cerr << idx << ' ';
			if (idx != 0 && L[idx - 1] != -1)
			{
				if (R[idx + 1] != -1)
				{
					res += solve(L[idx - 1], R[idx + 1]);
					res -= solve(L[idx - 1], idx - 1);
					res -= solve(idx + 1, R[idx + 1]);
					R[L[idx - 1]] = R[idx + 1];
					L[R[idx + 1]] = L[idx - 1];
				}
				else
				{
					res += solve(L[idx - 1], idx);
					res -= solve(L[idx - 1], idx - 1);
					L[idx] = L[idx - 1];
					R[L[idx]] = idx;
				}
			}
			else
			{
				if (R[idx + 1] != -1)
				{
					res += solve(idx, R[idx + 1]);
					res -= solve(idx + 1, R[idx + 1]);
					R[idx] = R[idx + 1];
					L[R[idx]] = idx;
				}
				else
				{
					res += solve(idx, idx);
					L[idx] = idx;
					R[idx] = idx;
				}
			}
		}
		cerr << endl;
		ans[i] = res % INF;
	}
	//0, 1, 3, 4, 5, 6, 10, 11, 12, 21, 22, 23
	cerr << solve(0, 1) << ' ' << solve(3, 6) << ' ' << solve(10, 12) << ' ' << solve(21, 23) << endl;
	for (int i = 1; i <= S; i++)
	{
		cout << ans[i] << ' ';
	}
	cout << '\n';
	return 0;
}


/*
PROG: cf906e
LANG: C++11
    _____
  .'     '.
 /  0   0  \
|     ^     |
|  \     /  |
 \  '---'  /
  '._____.'
 */
#include <bits/stdc++.h>

using namespace std;

long long readi()
{
	long long input = 0;
	char c = ' ';
	while (c < '-')
	{
		c = getchar();
	}
	bool negative = false;
	if (c == '-')
	{
		negative = true;
		c = getchar();
	}
	while (c >= '0')
	{
		input = 10 * input + (c - '0');
		c = getchar();
	}
	if (negative)
	{
		input = -input;
	}
	return input;
}
void printi(long long output)
{
	if (output == 0)
	{
		putchar('0');
		return;
	}
	if (output < 0)
	{
		putchar('-');
		output = -output;
	}
	int aout[20];
	int ilen = 0;
	while(output)
	{
		aout[ilen] = ((output % 10));
		output /= 10;
		ilen++;
	}
	for (int i = ilen - 1; i >= 0; i--)
	{
		putchar(aout[i] + '0');
	}
	return;
}
string reads()
{
	string input = "";
	char c = ' ';
	while (c <= ' ')
	{
		c = getchar();
	}
	while (c > ' ')
	{
		input += c;
		c = getchar();
	}
	return input;
}
int sgn(long long x)
{
	if (x < 0)
	{
		return -1;
	}
	if (x > 0)
	{
		return 1;
	}
	return 0;
}
long long randomize(long long x)
{
	return (((1ll << 31) * rand()) + rand()) % x;
}

#define MP make_pair
#define PB push_back
#define PF push_front
#define LB lower_bound
#define UB upper_bound
#define fi first
#define se second

const long double PI = 4.0 * atan(1.0);
const long double EPS = 1e-30;

#define SINF 10007
#define CO 1000007
#define INF 1000000007
#define BIG 1000000931
#define LARGE 1696969696967ll
#define GIANT 2564008813937411ll
#define LLINF 2696969696969696969ll

long long normalize(long long x, long long mod)
{
	return (((x % mod) + mod) % mod);
}

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

int32_t main()
{
	ios_base::sync_with_stdio(0);
	srand(time(0));
	//	cout << fixed << setprecision(12);
	//	cerr << fixed << setprecision(12);
	if (fopen("cf906e.in", "r"))
	{
		freopen ("cf906e.in", "r", stdin);
		freopen ("cf906e.out", "w", stdout);
	}
}


/*
PROG: cf452e
LANG: C++11
    _____
  .'     '.
 /  0   0  \
|     ^     |
|  \     /  |
 \  '---'  /
  '._____.'
 */
#include <bits/stdc++.h>

using namespace std;

long long readi()
{
	long long input = 0;
	char c = ' ';
	while (c < '-')
	{
		c = getchar();
	}
	bool negative = false;
	if (c == '-')
	{
		negative = true;
		c = getchar();
	}
	while (c >= '0')
	{
		input = 10 * input + (c - '0');
		c = getchar();
	}
	if (negative)
	{
		input = -input;
	}
	return input;
}
void printi(long long output)
{
	if (output == 0)
	{
		putchar('0');
		return;
	}
	if (output < 0)
	{
		putchar('-');
		output = -output;
	}
	int aout[20];
	int ilen = 0;
	while(output)
	{
		aout[ilen] = ((output % 10));
		output /= 10;
		ilen++;
	}
	for (int i = ilen - 1; i >= 0; i--)
	{
		putchar(aout[i] + '0');
	}
	return;
}
string reads()
{
	string input = "";
	char c = ' ';
	while (c <= ' ')
	{
		c = getchar();
	}
	while (c > ' ')
	{
		input += c;
		c = getchar();
	}
	return input;
}
int sgn(long long x)
{
	if (x < 0)
	{
		return -1;
	}
	if (x > 0)
	{
		return 1;
	}
	return 0;
}
long long randomize(long long x)
{
	return (((1ll << 31) * rand()) + rand()) % x;
}

#define MP make_pair
#define PB push_back
#define PF push_front
#define LB lower_bound
#define UB upper_bound
#define fi first
#define se second

const long double PI = 4.0 * atan(1.0);
const long double EPS = 1e-30;

#define SINF 10007
#define CO 1000007
#define INF 1000000007
#define BIG 1000000931
#define LARGE 1696969696967ll
#define GIANT 2564008813937411ll
#define LLINF 2696969696969696969ll
#define MAXN 300010
#define LOG 21

long long normalize(long long x, long long mod)
{
	return (((x % mod) + mod) % mod);
}

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

string temp;
int N, M, K, S;
int A[MAXN], B[MAXN], C[MAXN];
ll pref[MAXN][4], ans[MAXN];
int id[MAXN];
vector<int> v[MAXN];
int dsu[MAXN];
int L[MAXN], R[MAXN];
ll res;

struct suffixarray
{
	vector<int> s;
	int best;
	int sval[LOG + 2][MAXN];
	int suf[MAXN], srank[MAXN], lcp[MAXN];
	vector<int> sfi[MAXN], sse[MAXN];
	void getsuf()
	{
		for (int i = 0; i < s.size(); i++)
		{
			sval[0][i] = s[i];
		}
		for (int i = 0; i < LOG; i++)
		{
			int Z = max((int) s.size(), 256);
			for (int j = 0; j <= Z; j++)
			{
				sse[j].clear();
				sfi[j].clear();
			}
			for (int j = 0; j < s.size(); j++)
			{
				sse[sval[i][j + (1 << i)]].PB(j);
			}
			for (int j = 0; j <= Z; j++)
			{
				for (int k = 0; k < sse[j].size(); k++)
				{
					int idx = sse[j][k];
					sfi[sval[i][idx]].PB(idx);
				}
			}
			int cnt = 0;
			pii was = MP(-1, -1);
			for (int j = 0; j <= Z; j++)
			{
				for (int k = 0; k < sfi[j].size(); k++)
				{
					int idx = sfi[j][k];
					pii curp = MP(sval[i][idx], sval[i][idx + (1 << i)]);
					if (curp != was)
					{
						cnt++;
						was = curp;
					}
					sval[i + 1][idx] = cnt;
				}
			}
		}
		for (int i = 0; i < s.size(); i++)
		{
			srank[i] = sval[LOG][i] - 1;
			suf[srank[i]] = i;
		}
	}
	void getlcp()
	{
		for (int i = 0; i < s.size(); i++)
		{
			if (srank[i] == s.size() - 1)
			{
				best = 0;
				continue;
			}
			int idx = suf[srank[i] + 1];
			while(i + best < s.size() && idx + best < s.size() && s[i + best] == s[idx + best])
			{
				best++;
			}
			lcp[srank[i]] = best;
			best--;
			best = max(0, best);
		}
	}
};

suffixarray sfx;

ll solve(int L, int R)
{
	R++;
	ll ca = pref[R + 1][0] - pref[L][0];
	ll cb = pref[R + 1][1] - pref[L][1];
	ll cc = pref[R + 1][2] - pref[L][2];
	return (ca * cb * cc);
}

int32_t main()
{
	ios_base::sync_with_stdio(0);
	srand(time(0));
	//	cout << fixed << setprecision(12);
	//	cerr << fixed << setprecision(12);
	if (fopen("cf452e.in", "r"))
	{
		freopen ("cf452e.in", "r", stdin);
		freopen ("cf452e.out", "w", stdout);
	}
	cin >> temp;
	N = temp.length();
	for (int i = 0; i < N; i++)
	{
		A[i] = temp[i] - 'a' + 1;
	}
	cin >> temp;
	M = temp.length();
	for (int i = 0; i < M; i++)
	{
		B[i] = temp[i] - 'a' + 1;
	}
	cin >> temp;
	K = temp.length();
	for (int i = 0; i < K; i++)
	{
		C[i] = temp[i] - 'a' + 1;
	}
	S = min(N, min(M, K));
	for (int i = 0; i < N; i++)
	{
		sfx.s.PB(A[i]);
		id[sfx.s.size() - 1] = 0;
	}
	sfx.s.PB(27);
	id[sfx.s.size() - 1] = 3;
	for (int i = 0; i < M; i++)
	{
		sfx.s.PB(B[i]);
		id[sfx.s.size() - 1] = 1;
	}
	sfx.s.PB(28);
	id[sfx.s.size() - 1] = 3;
	for (int i = 0; i < K; i++)
	{
		sfx.s.PB(C[i]);
		id[sfx.s.size() - 1] = 2;
	}
	sfx.getsuf();
	sfx.getlcp();
	for (int i = 0; i < sfx.s.size(); i++)
	{
		for (int j = 0; j < 3; j++)
		{
			pref[i + 1][j] = pref[i][j];
		}
		pref[i + 1][id[sfx.suf[i]]]++;
//		cerr << id[sfx.suf[i]] << endl;
	}
	for (int i = 0; i < sfx.s.size() - 1; i++)
	{
		v[sfx.lcp[i]].PB(i);
//		cerr << sfx.lcp[i] << ' ';
	}
//	cerr << endl;
	for (int i = 0; i <= sfx.s.size() + 2; i++)
	{
		L[i] = -1;
		R[i] = -1;
	}
	for (int i = S; i > 0; i--)
	{
		for (int idx : v[i])
		{
//			cerr << idx << ' ';
			if (idx != 0 && L[idx - 1] != -1)
			{
				if (R[idx + 1] != -1)
				{
					res += solve(L[idx - 1], R[idx + 1]);
					res -= solve(L[idx - 1], idx - 1);
					res -= solve(idx + 1, R[idx + 1]);
					R[L[idx - 1]] = R[idx + 1];
					L[R[idx + 1]] = L[idx - 1];
				}
				else
				{
					res += solve(L[idx - 1], idx);
					res -= solve(L[idx - 1], idx - 1);
					L[idx] = L[idx - 1];
					R[L[idx]] = idx;
				}
			}
			else
			{
				if (R[idx + 1] != -1)
				{
					res += solve(idx, R[idx + 1]);
					res -= solve(idx + 1, R[idx + 1]);
					R[idx] = R[idx + 1];
					L[R[idx]] = idx;
				}
				else
				{
					res += solve(idx, idx);
					L[idx] = idx;
					R[idx] = idx;
				}
			}
		}
//		cerr << endl;
		ans[i] = res % INF;
	}
	//0...5 7....9 11...12
	for (int i = 1; i <= S; i++)
	{
		cout << ans[i] << ' ';
	}
	cout << '\n';
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define db(x) cerr << #x << "=" << x << endl
#define db2(x, y) cerr << #x << "=" << x << "," << #y << "=" << y << endl
#define db3(x, y, z) cerr << #x << "=" << x << "," << #y << "=" << y << "," << #z << "=" << z << endl
#define dbv(v) cerr << #v << "="; for (auto x : v) cerr << x << ", "; cerr << endl
#define dba(a, n) cerr << #a << "="; for (int i = 0; i < (n); ++i) cerr << a[i] << ", "; cerr << endl
typedef long long ll;
typedef long double ld;
const int MAXN = 300005;
const int INF = 1000000000;
char S[MAXN];
struct Node {
	map<int, Node*> to;
	int len, fchar;
	int num[3];
	Node *link;
	Node(int fchar, int len): fchar(fchar), len(len) {
		fill(num, num + 3, 0);
	}
};
Node *node, *root;
int pos, curn;
void init() {
	node = root = new Node(0, 0);
	pos = curn = 0;
}
void goDown() {
	for (;;) {
		Node *next = node->to[S[curn - pos]];
		if (!next || pos <= next->len) return;
		node = next;
		pos -= node->len;
	}
}
void addLetter() {
	int c = S[curn++];
	++pos;
	Node *last = nullptr;
	// While there are still suffixes to add
	while (pos) {
		goDown();
		int edge = S[curn - pos];
		Node *&v = node->to[edge];
		if (!v) {
			v = new Node(curn - pos, INF);
			if (last) last->link = node;
			last = nullptr; // Leaf has no suffix link
		} else {
			int t = S[v->fchar + pos - 1];
			if (t == c) {
				// We followed a letter on the edge
				if (last) last->link = node;
				return;
			} else {
				Node *u = new Node(v->fchar, pos - 1);
				u->to[c] = new Node(curn - 1, INF);
				u->to[t] = v;
				v->fchar += pos - 1;
				v->len -= pos - 1;
				v = u;
				if (last) last->link = u;
				last = u;
			}
		}
		if (node == root) --pos;
		else node = node->link;
	}
}
const ll MOD = 1000000007;
ll delta[MAXN];
int len, len1, len2, len3;
void go(Node *x, int h = 0) {
	if (x->len > len) {
		if (x->fchar <= len1) ++x->num[0];
		else if (x->fchar <= len1 + len2 + 1) ++x->num[1];
		else ++x->num[2];
		assert(x->to.empty());
		return;
	}
	h += x->len;
	for (auto m : x->to) {
		char c = m.first;
		go(m.second, h);
		for (int i = 0; i < 3; ++i)
			x->num[i] += m.second->num[i];
	}
	int st = h - x->len + 1;
	int en = h + 1;
	ll val = (ll)x->num[0] * x->num[1] * x->num[2];
	delta[st] += val;
	delta[st] %= MOD;
	delta[en] -= val;
	delta[en] %= MOD;
}
int main() {
	scanf("%s", S);
	len1 = strlen(S);
	S[len1] = '0';
	scanf("%s", S + len1 + 1);
	len2 = strlen(S + len1 + 1);
	S[len1 + len2 + 1] = '1';
	scanf("%s", S + len1 + len2 + 2);
	len3 = strlen(S + len1 + len2 + 2);
	S[len1 + len2 + len3 + 2] = '2';
	len = len1 + len2 + len3 + 3;
	S[len] = '\0';
	init();
	for (int i = 0; i < len; ++i) {
		addLetter();
	}
	go(root);
	int mlen = min(len1, min(len2, len3));
	ll add = 0;
	for (int i = 1; i <= mlen; ++i) {
		add += delta[i];
		add %= MOD;
		if (add < 0) add += MOD;
		printf("%lld ", add);
	}
}


#include <bits/stdc++.h>

using namespace std;
using namespace placeholders;

template <class T> void mini(T &l, T r) {l = min(l, r);}
template <class T> void maxi(T &l, T r) {l = max(l, r);}

template <class TH> void _dbg(const char *sdbg, TH h) {
  cerr << sdbg << "=" << h << "\n";
}
template <class TH, class ...TA> void _dbg(const char *sdbg, TH h, TA ...a) {
  while (*sdbg != ',') cerr << *sdbg++; cerr << "=" << h << ","; _dbg(sdbg + 1, a...);
}
template <class T> ostream &operator<<(ostream &os, vector <T> v) {
  os << "[";
  for (auto vv : v) os << vv << ",";
  return os << "]";
}
template <class L, class R> ostream &operator<<(ostream &os, pair <L, R> p) {
  return os << "(" << p.first << "," << p.second << ")";
}

#define eput(...) //_dbg(#__VA_ARGS__, __VA_ARGS__)

using llint = long long;

const int N = 3e5 + 10, SIG = 30, B = 1e9 + 7;

vector <int> e[N << 1];
char s[3][N];
llint d[N];

struct Node {
  Node *ch[SIG], *fa;
  int sz[3];
  int len;
  Node() : len(0), fa(NULL) {
    memset(ch, 0, sizeof(ch));
    memset(sz, 0, sizeof(sz));
  }
} pool[(N << 1) + 5], *last, *root;

void add_edge(int x, int y) {
  e[x].push_back(y);
}

namespace SAM {

int cnt;

void init() {
  if (cnt)
    for (int i = 0; i < cnt; ++i)
      pool[i] = Node();
  cnt = 1;
  root = &pool[0];
  last = root;
}

void add(int c, int j) {
  Node *np = &pool[cnt++];
  np->sz[j] = 1;
  np->len = last->len + 1;
  Node *p = last;
  while (p && !p->ch[c]) {
    p->ch[c] = np;
    p = p->fa;
  }
  if (!p) {
    np->fa = root;
  } else {
    Node *q = p->ch[c];
    if (q->len != p->len + 1) {
      Node *nq = &pool[cnt++];
      nq->len = p->len + 1;
      for (int i = 0; i < SIG; ++i) nq->ch[i] = q->ch[i];
      nq->fa = q->fa;
      //nq->sz should be 0 because q->fa = nq, in later code q->sz will be added to q->fa->sz i.e. nq->sz, so no nq->sz = q->sz
      //nq->sz = q->sz;
      q->fa = np->fa = nq;
      while (p && p->ch[c] == q) {
	p->ch[c] = nq;
	p = p->fa;
      }
    } else {
      np->fa = q;
    }
  }
  last = np;
}

void add_fa_tree() {
  for (int i = 1; i < cnt; ++i) {
    assert(pool[i].fa - pool != i);
    add_edge(pool[i].fa - pool, i);
  }
}

void dfs(int v, int f) {
  for (int u : e[v]) {
    if (u == f) continue;
    dfs(u, v);
    for (int j = 0; j < 3; ++j)
      pool[v].sz[j] += pool[u].sz[j];
  }
}

}

void add(llint &a, llint b) {
  a = (a + b) % B;
  if (a < 0) a += B;
}

void add(int l, int r, llint b) {
  eput(l, r, b);
  add(d[l], b);
  add(d[r + 1], -b);
}

llint calc(const Node &a) {
  return 1ll * a.sz[0] * a.sz[1] % B * a.sz[2] % B;
}

void run() {
  SAM::init();
  for (int i = 0; i < 3; ++i) scanf("%s", s[i]);
  int mn_len = N;
  for (int i = 0; i < 3; ++i) {
    int m = strlen(s[i]);
    mn_len = min(mn_len, m);
    for (int j = 0; j < m; ++j) {
      SAM::add(s[i][j] - 'a', i);
    }
    SAM::add(26 + i, i);
  }
  SAM::add_fa_tree();
  SAM::dfs(0, 0);

  for (int i = 1; i < SAM::cnt; ++i) {
    int l = pool[i].fa->len + 1, r = pool[i].len;
    add(l, r, calc(pool[i]));
  }

  for (int i = 1; i <= mn_len; ++i) {
    add(d[i], d[i - 1]);
  }

  for (int i = 1; i <= mn_len; ++i) printf("%lld%c", d[i], " \n"[i == mn_len]);
}

int main() {
  run();
  return 0;
}


#include <bits/stdc++.h>

using namespace std;
using namespace placeholders;

template <class T> void mini(T &l, T r) {l = min(l, r);}
template <class T> void maxi(T &l, T r) {l = max(l, r);}

template <class TH> void _dbg(const char *sdbg, TH h) {
  cerr << sdbg << "=" << h << "\n";
}
template <class TH, class ...TA> void _dbg(const char *sdbg, TH h, TA ...a) {
  while (*sdbg != ',') cerr << *sdbg++; cerr << "=" << h << ","; _dbg(sdbg + 1, a...);
}
template <class T> ostream &operator<<(ostream &os, vector <T> v) {
  os << "[";
  for (auto vv : v) os << vv << ",";
  return os << "]";
}
template <class L, class R> ostream &operator<<(ostream &os, pair <L, R> p) {
  return os << "(" << p.first << "," << p.second << ")";
}

#define eput(...) //_dbg(#__VA_ARGS__, __VA_ARGS__)

using llint = long long;

const int N = 3e5 + 10, SIG = 30, B = 1e9 + 7;

vector <int> e[N << 1];
char s[3][N];
llint d[N];

struct Node {
  Node *ch[SIG], *fa;
  int sz[3];
  int len;
  Node() : len(0), fa(NULL) {
    memset(ch, 0, sizeof(ch));
    memset(sz, 0, sizeof(sz));
  }
} pool[(N << 1) + 5], *last, *root;

void add_edge(int x, int y) {
  e[x].push_back(y);
}

namespace SAM {

int cnt;

void init() {
  if (cnt)
    for (int i = 0; i < cnt; ++i)
      pool[i] = Node();
  cnt = 1;
  root = &pool[0];
  last = root;
}

void add(int c, int j) {
  Node *np = &pool[cnt++];
  np->sz[j] = 1;
  np->len = last->len + 1;
  Node *p = last;
  while (p && !p->ch[c]) {
    p->ch[c] = np;
    p = p->fa;
  }
  if (!p) {
    np->fa = root;
  } else {
    Node *q = p->ch[c];
    if (q->len != p->len + 1) {
      Node *nq = &pool[cnt++];
      nq->len = p->len + 1;
      for (int i = 0; i < SIG; ++i) nq->ch[i] = q->ch[i];
      nq->fa = q->fa;
      //nq->sz should be 0 because q->fa = nq, in later code q->sz will be added to q->fa->sz i.e. nq->sz, so no nq->sz = q->sz
      //nq->sz = q->sz;
      q->fa = np->fa = nq;
      while (p && p->ch[c] == q) {
	p->ch[c] = nq;
	p = p->fa;
      }
    } else {
      np->fa = q;
    }
  }
  last = np;
}

void add_fa_tree() {
  for (int i = 1; i < cnt; ++i) {
    assert(pool[i].fa - pool != i);
    add_edge(pool[i].fa - pool, i);
  }
}

void dfs(int v, int f) {
  for (int u : e[v]) {
    if (u == f) continue;
    dfs(u, v);
    for (int j = 0; j < 3; ++j)
      pool[v].sz[j] += pool[u].sz[j];
  }
}

}

void add(llint &a, llint b) {
  a = (a + b) % B;
  if (a < 0) a += B;
}

void add(int l, int r, llint b) {
  eput(l, r, b);
  add(d[l], b);
  add(d[r + 1], -b);
}

llint calc(const Node &a) {
  return a.sz[0] * a.sz[1] % B * a.sz[2] % B;
}

void run() {
  SAM::init();
  for (int i = 0; i < 3; ++i) scanf("%s", s[i]);
  int mn_len = N;
  for (int i = 0; i < 3; ++i) {
    int m = strlen(s[i]);
    mn_len = min(mn_len, m);
    for (int j = 0; j < m; ++j) {
      SAM::add(s[i][j] - 'a', i);
    }
    SAM::add(26 + i, i);
  }
  SAM::add_fa_tree();
  SAM::dfs(0, 0);

  for (int i = 1; i < SAM::cnt; ++i) {
    int l = pool[i].fa->len + 1, r = pool[i].len;
    add(l, r, calc(pool[i]));
  }

  for (int i = 1; i <= mn_len; ++i) {
    add(d[i], d[i - 1]);
  }

  for (int i = 1; i <= mn_len; ++i) printf("%lld%c", d[i], " \n"[i == mn_len]);
}

int main() {
  run();
  return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
#define N 600010
#define D 27
using namespace std;
int n,cnt=1,pos,f[N],fa[N],ch[N][D],C[N];
char s[N];int ans,len=N,g[N][3],k,la[N],ff[N];
bool cmp(const int &a,const int &b){return f[a]<f[b];}
struct node{int a,b;}e[N];
void add(int a,int b){
  e[++k]=(node){a,b};ff[k]=la[a];la[a]=k;
}

class SAM{
  public:
  int build(int x,int c,int p)
  {
    int nx=++cnt;f[nx]=f[x]+1;g[nx][p]=1;
    while(x&&!ch[x][c])ch[x][c]=nx,x=fa[x];
    if(!x)fa[nx]=1;
    else
	{
      int p=ch[x][c];
      if(f[p]==f[x]+1)fa[nx]=p;
      else
	  {
        int np=++cnt;f[np]=f[x]+1;
        memcpy(ch[np],ch[p],sizeof(ch[p]));
        fa[np]=fa[p];fa[nx]=fa[p]=np;
        while(x&&ch[x][c]==p)ch[x][c]=np,x=fa[x];
      }
    }
    return nx;
  }
  void dfs(int x)
  {
    for(int a=la[x];a;a=ff[a])
    {
	  dfs(e[a].b);
	  for(int j=0;j<3;j++)(g[x][j]+=g[e[a].b][j])%=mod;
	}
	int val=(ll)g[x][0]*g[x][1]%mod*g[x][2]%mod;
    (C[f[fa[x]]+1]+=val)%=mod;
	(C[f[x]+1]+=mod-val)%=mod;
  }
}S;

int main()
{
  int x,val;
  for(int i=0;i<3;i++)
  {
    scanf(" %s",s);n=strlen(s);
	len=min(len,n);pos=1;
    for(int j=0;j<n;j++)
    {
      x=ch[pos][s[j]-'a'];
      if(x&&f[x]==j+1)g[x][i]++,pos=x;
	  else pos=S.build(pos,s[j]-'a',i);
    }
  }
  for(int i=1;i<=cnt;i++)add(fa[i],i);
  S.dfs(1);
  for(int i=1;i<=len;i++)
    (C[i]+=C[i-1])%=mod,printf("%d ",C[i]);
  printf("\n");
  return 0;
}


#include<bits/stdc++.h>
using namespace std;

const int N=600010;
const int mod=1000000007;
typedef long long ll;
int n,c[N],rk[N],tot,head[N];
ll sum[N];
char s[N];
struct Edge{
	int suiv,ver;
}e[N<<1];

inline void lnk(int x,int y)
{
	e[++tot].ver=y;
	e[tot].suiv=head[x];
	head[x]=tot;
}

struct SuffixAutomaton{
	int cnt,fa[N],len[N],c[N][26],siz[N][3];
	SuffixAutomaton(){cnt=1;}
	inline void extend(int &lst,int ch,int id)
	{
		int p=lst,now=lst=++cnt;
		len[now]=len[p]+1,siz[now][id]=1;
		while(p && !c[p][ch])c[p][ch]=now,p=fa[p];
		if(!p)return fa[now]=1,void();
		int q=c[p][ch];
		if(len[q]==len[p]+1)fa[now]=q;
		else
		{
			int nou=++cnt;len[nou]=len[p]+1;
			memcpy(c[nou],c[q],sizeof(c[q]));
			fa[nou]=fa[q];fa[q]=fa[now]=nou;
			while(p && c[p][ch]==q)c[p][ch]=nou,p=fa[p];
		}
	}
	inline void dfs(int x)
	{
		for(int i=head[x];i;i=e[i].suiv)
		{
			int y=e[i].ver;dfs(y);
			for(int j=0;j<3;j++)
				siz[x][j]+=siz[y][j];
		}
	}
	inline void init()
	{
		for(int i=2;i<=cnt;i++)lnk(fa[i],i);
		dfs(1);
	}
}t;

int main()
{
	int mini=0x3f3f3f3f;
	for(int i=0;i<3;i++)
	{
		scanf("%s",s+1);
		mini=min(mini,n=strlen(s+1));
		for(int j=1,lst=1;j<=n;j++)
			t.extend(lst,s[j]-'a',i);
	}
	t.init();
	for(int i=2;i<=t.cnt;i++)
	{
		ll pos=1ll*t.siz[i][0]*t.siz[i][1]%mod*t.siz[i][2]%mod;
		sum[t.len[t.fa[i]]+1]+=pos,sum[t.len[i]+1]-=pos;
	}
	for(int i=1;i<=mini;i++)
		sum[i]+=sum[i-1],sum[i]=(sum[i]%mod+mod)%mod,
		printf("%lld ",sum[i]);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;

const int N=600010;
const int mod=1000000007;
typedef long long ll;
int n,c[N],rk[N],tot,head[N];
ll sum[N];
char s[N];
struct Edge{
	int suiv,ver;
}e[N<<1];

inline void lnk(int x,int y)
{
	e[++tot].ver=y;
	e[tot].suiv=head[x];
	head[x]=tot;
}

struct SuffixAutomaton{
	int cnt,fa[N],len[N],c[N][26],siz[N][3];
	SuffixAutomaton(){cnt=1;}
	inline int extend(int &lst,int ch,int id)
	{
//		if(c[lst][ch]&&len[lst]+1==len[c[lst][ch]])
//			return c[lst][ch];
		int p=lst,now=lst=++cnt,fg=0;
		len[now]=len[p]+1,siz[now][id]=1;
		while(p && !c[p][ch])c[p][ch]=now,p=fa[p];
		if(!p)return fa[now]=1,now;
		int q=c[p][ch],nou;
		if(len[q]==len[p]+1)fa[now]=q;
		else
		{
			if(p==lst)fg=1;
			nou=++cnt;len[nou]=len[p]+1;
			memcpy(c[nou],c[q],sizeof(c[q]));
			fa[nou]=fa[q];fa[q]=fa[now]=nou;
			while(p && c[p][ch]==q)c[p][ch]=nou,p=fa[p];
		}
		return fg?nou:now;
	}
	inline void dfs(int x)
	{
		for(int i=head[x];i;i=e[i].suiv)
		{
			int y=e[i].ver;dfs(y);
			for(int j=0;j<3;j++)
				siz[x][j]+=siz[y][j];
		}
	}
	inline void init()
	{
		for(int i=2;i<=cnt;i++)lnk(fa[i],i);
		dfs(1);
	}
}t;

int main()
{
	int mini=0x3f3f3f3f;
	for(int i=0;i<3;i++)
	{
		scanf("%s",s+1);
		mini=min(mini,n=strlen(s+1));
		for(int j=1,lst=1;j<=n;j++)
			t.extend(lst,s[j]-'a',i);
	}

//	for(int i=2;i<=t.cnt;i++)
//		cout<<t.siz[i][0]<<" "<<t.siz[i][1]<<" "<<t.siz[i][2]<<endl;
	t.init();
//	for(int i=1;i<=t.cnt;i++)c[t.len[i]]++;
//	for(int i=1;i<=t.cnt;i++)c[i]+=c[i-1];
//	for(int i=t.cnt;i;i--)rk[c[t.len[i]]--]=i;
//	for(int i=t.cnt;i;i--)
//	{
//		int x=rk[i];
//		for(int j=0;j<3;j++)
//			(t.siz[t.fa[x]][j]+=t.siz[x][j])%=mod;
//	}
	for(int i=2;i<=t.cnt;i++)
	{
//		cout<<t.siz[i][0]<<" "<<t.siz[i][1]<<" "<<t.siz[i][2]<<endl;
		ll pos=1ll*t.siz[i][0]*t.siz[i][1]%mod*t.siz[i][2]%mod;
//		cout<<" i "<<i<<" "<<pos<<endl;
		sum[t.len[t.fa[i]]+1]+=pos,sum[t.len[i]+1]-=pos;
	}
	for(int i=1;i<=mini;i++)
		sum[i]+=sum[i-1],sum[i]=(sum[i]%mod+mod)%mod,
		printf("%lld ",sum[i]);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;

#define all(s) s.begin(), s.end()
#define pb push_back
#define ii pair<int, int>
#define x first
#define y second
#define bit(x, y) ((x >> y) & 1)

// Source: http://codeforces.com/contest/452/submission/7269543
// Efficient Suffix Array O(N*logN)

// String index from 0
// Usage:
// string s;  (s[i] > 0)
// SuffixArray sa(s);
// Now we can use sa.SA and sa.LCP
// sa.LCP[i] = max common prefix suffix of sa.SA[i-1] and sa.SA[i]
struct SuffixArray {
    string a;
    int N, m;
    vector<int> SA, LCP, x, y, w, c;

    SuffixArray(string _a, int m = 256) : a(" " + _a), N(a.length()), m(m),
            SA(N), LCP(N), x(N), y(N), w(max(m, N)), c(N) {
        a[0] = 0;
        DA();
        kasaiLCP();
        #define REF(X) { rotate(X.begin(), X.begin()+1, X.end()); X.pop_back(); }
        REF(SA); REF(LCP);
        a = a.substr(1, a.size());
        for(int i = 0; i < (int) SA.size(); ++i) --SA[i];
        #undef REF
    }

    inline bool cmp (const int a, const int b, const int l) { return (y[a] == y[b] && y[a + l] == y[b + l]); }

    void Sort() {
        for(int i = 0; i < m; ++i) w[i] = 0;
        for(int i = 0; i < N; ++i) ++w[x[y[i]]];
        for(int i = 0; i < m - 1; ++i) w[i + 1] += w[i];
        for(int i = N - 1; i >= 0; --i) SA[--w[x[y[i]]]] = y[i];
    }

    void DA() {
        for(int i = 0; i < N; ++i) x[i] = a[i], y[i] = i;
        Sort();
        for(int i, j = 1, p = 1; p < N; j <<= 1, m = p) {
            for(p = 0, i = N - j; i < N; i++) y[p++] = i;
            for (int k = 0; k < N; ++k) if (SA[k] >= j) y[p++] = SA[k] - j;
            Sort();
            for(swap(x, y), p = 1, x[SA[0]] = 0, i = 1; i < N; ++i)
                x[SA[i]] = cmp(SA[i - 1], SA[i], j) ? p - 1 : p++;
        }
    }

    void kasaiLCP() {
        for (int i = 0; i < N; i++) c[SA[i]] = i;
        for (int i = 0, j, k = 0; i < N; LCP[c[i++]] = k)
            if (c[i] > 0) for (k ? k-- : 0, j = SA[c[i] - 1]; a[i + k] == a[j + k]; k++);
            else k = 0;
    }
};

string s[3];

int stringId(int id) {
    if (id >= 0 && id < s[0].size()) return 0;
    if (id > s[0].size() && id < s[0].size() + s[1].size() + 1) return 1;
    if (id > s[0].size() + s[1].size() + 1 && id < s[0].size() +s[1].size() + s[2].size() + 2) return 2;
    return -1;
}

const int N = 300005;
const int MOD = 1000000007;

int cnt[N][3];
int p[N];
vector<int> v[N];
int l;
int ans[N];

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

void merge(int u, int v, int &plus) {
    if ((u = root(u)) == (v = root(v))) return;
    long long temp = 0;
    temp -= 1LL * cnt[u][0] * cnt[u][1] * cnt[u][2] % MOD;
    temp -= 1LL * cnt[v][0] * cnt[v][1] * cnt[v][2] % MOD;
    p[v] = u;
    for (int i = 0; i < 3; i++) cnt[u][i] += cnt[v][i];
    temp += 1LL * cnt[u][0] * cnt[u][1] * cnt[u][2] % MOD;
    temp = (temp % MOD + MOD) % MOD;
    plus += temp;
    plus %= MOD;
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    cout.tie(0);
    cin >> s[0] >> s[1] >> s[2];
    l = min(s[0].size(), min(s[1].size(), s[2].size()));
    string t = s[0] + "$" + s[1] + "&" + s[2];
    SuffixArray sa = SuffixArray(t);
    int n = t.size();
    for (int i = 0; i < n; i++) {
        p[i] = i;
        int foo = stringId(sa.SA[i]);
        if (foo != -1) cnt[i][foo] = 1;
        v[sa.LCP[i]].pb(i);
    }
    // for (int i = 0; i < n; i++) {
    //     cout << sa.SA[i] << ' ';
    // }
    // cout << endl;
    // for (int i = 0; i < n; i++) {
    //     cout << sa.LCP[i] << ' ';
    // }
    // cout << endl;
    int plus = 0;
    for (int i = l; i >= 1; i--) {
        for (int e : v[i]) {
            merge(e - 1, e, plus);
        }
        ans[i] = (ans[i + 1] + plus) % MOD;
        plus = 0;
    }
    for (int i = 1; i <= l; i++) cout << ans[i] << ' ';
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

#define all(s) s.begin(), s.end()
#define pb push_back
#define ii pair<int, int>
#define x first
#define y second
#define bit(x, y) ((x >> y) & 1)

// Source: http://codeforces.com/contest/452/submission/7269543
// Efficient Suffix Array O(N*logN)

// String index from 0
// Usage:
// string s;  (s[i] > 0)
// SuffixArray sa(s);
// Now we can use sa.SA and sa.LCP
// sa.LCP[i] = max common prefix suffix of sa.SA[i-1] and sa.SA[i]
struct SuffixArray {
    string a;
    int N, m;
    vector<int> SA, LCP, x, y, w, c;

    SuffixArray(string _a, int m = 256) : a(" " + _a), N(a.length()), m(m),
            SA(N), LCP(N), x(N), y(N), w(max(m, N)), c(N) {
        a[0] = 0;
        DA();
        kasaiLCP();
        #define REF(X) { rotate(X.begin(), X.begin()+1, X.end()); X.pop_back(); }
        REF(SA); REF(LCP);
        a = a.substr(1, a.size());
        for(int i = 0; i < (int) SA.size(); ++i) --SA[i];
        #undef REF
    }

    inline bool cmp (const int a, const int b, const int l) { return (y[a] == y[b] && y[a + l] == y[b + l]); }

    void Sort() {
        for(int i = 0; i < m; ++i) w[i] = 0;
        for(int i = 0; i < N; ++i) ++w[x[y[i]]];
        for(int i = 0; i < m - 1; ++i) w[i + 1] += w[i];
        for(int i = N - 1; i >= 0; --i) SA[--w[x[y[i]]]] = y[i];
    }

    void DA() {
        for(int i = 0; i < N; ++i) x[i] = a[i], y[i] = i;
        Sort();
        for(int i, j = 1, p = 1; p < N; j <<= 1, m = p) {
            for(p = 0, i = N - j; i < N; i++) y[p++] = i;
            for (int k = 0; k < N; ++k) if (SA[k] >= j) y[p++] = SA[k] - j;
            Sort();
            for(swap(x, y), p = 1, x[SA[0]] = 0, i = 1; i < N; ++i)
                x[SA[i]] = cmp(SA[i - 1], SA[i], j) ? p - 1 : p++;
        }
    }

    void kasaiLCP() {
        for (int i = 0; i < N; i++) c[SA[i]] = i;
        for (int i = 0, j, k = 0; i < N; LCP[c[i++]] = k)
            if (c[i] > 0) for (k ? k-- : 0, j = SA[c[i] - 1]; a[i + k] == a[j + k]; k++);
            else k = 0;
    }
};

string s[3];

int stringId(int id) {
    if (id >= 0 && id < s[0].size()) return 0;
    if (id > s[0].size() && id < s[0].size() + s[1].size() + 1) return 1;
    if (id > s[0].size() + s[1].size() + 1 && id < s[0].size() +s[1].size() + s[2].size() + 2) return 2;
    return -1;
}

const int N = 300005;
const int MOD = 1000000007;

int cnt[N][3];
int p[N];
vector<int> v[N];
int l;
int ans[N];

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

void merge(int u, int v, int &plus) {
    if ((u = root(u)) == (v = root(v))) return;
    long long temp = 0;
    temp -= 1LL * cnt[u][0] * cnt[u][1] * cnt[u][2] % MOD;
    temp -= 1LL * cnt[v][0] * cnt[v][1] * cnt[v][2] % MOD;
    p[v] = u;
    for (int i = 0; i < 3; i++) cnt[u][i] += cnt[v][i];
    temp += 1LL * cnt[u][0] * cnt[u][1] * cnt[u][2] % MOD;
    temp = (temp % MOD + MOD) % MOD;
    plus += temp;
    plus %= MOD;
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    cout.tie(0);
    cin >> s[0] >> s[1] >> s[2];
    l = min(s[0].size(), min(s[1].size(), s[2].size()));
    string t = s[0] + "$" + s[1] + "&" + s[2];
    SuffixArray sa = SuffixArray(t);
    int n = t.size();
    for (int i = 0; i < n; i++) {
        p[i] = i;
        int foo = stringId(sa.SA[i]);
        if (foo != -1) cnt[i][foo] = 1;
        v[sa.LCP[i]].pb(i);
    }
    // for (int i = 0; i < n; i++) {
    //     cout << sa.SA[i] << ' ';
    // }
    // cout << endl;
    // for (int i = 0; i < n; i++) {
    //     cout << sa.LCP[i] << ' ';
    // }
    // cout << endl;
    int plus = 0;
    for (int i = n; i >= 1; i--) {
        for (int e : v[i]) {
            merge(e - 1, e, plus);
        }
        ans[i] = (ans[i + 1] + plus) % MOD;
        plus = 0;
    }
    for (int i = 1; i <= l; i++) cout << ans[i] << ' ';
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef int ll;
typedef unsigned long long ull;
const ll MAX=1e6+5;
const ll MAX_C=28;
ll MOD=1e9+7;
ll MOD1=1e9+9;
#define pb push_back
#define se second
#define fi first
#define db double
#define pdb pair<db,db>
#define maxe max_element
#define mine min_element
#define debug(x) cout<<#x<<" :: "<<x<<endl;
#define debug2(x,y) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<endl;
#define debug3(x,y,z) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\t"<<#z<<" :: "<<z<<endl;
#define debug4(x,y,z,w) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\t"<<#z<<" :: "<<z<<"\t"<<#w<<" :: "<<w<<endl;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define fbo find_by_order
#define ook order_of_key
#define ub upper_bound
#define lb lower_bound
#define pq priority_queue
#define pll pair<ll,ll>
#define boost               ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
using namespace __gnu_pbds;
#define ordered_set tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update>
#define dt pair<pll,ll>
int t[MAX][MAX_C],s[MAX],l[MAX],r[MAX],p[MAX],ts,tv,tp,i,n,n1,n2,n3;
string str;
ll cnt[MAX];
void ukkadd(ll c)
{
	while(1){
	if(r[tv]<tp){
		if(t[tv][c]==-1){t[tv][c]=ts;l[ts]=i;p[ts++]=tv;tv=s[tv];tp=r[tv]+1;continue;}
		tv=t[tv][c];tp=l[tv];
	}
	if(tp==-1 || c==str[tp]-'a'){
		tp++;break;
	}
	else{
		l[ts]=l[tv];p[ts]=p[tv];r[ts]=tp-1;t[ts][str[tp]-'a']=tv;
		l[ts+1]=i;p[ts+1]=ts;t[ts][c]=ts+1;
		l[tv]=tp;p[tv]=ts;t[p[ts]][str[l[ts]]-'a']=ts;
		tv=s[p[ts]];tp=l[ts];
		while(tp<=r[ts]){tv=t[tv][str[tp]-'a'];tp+=r[tv]-l[tv]+1;}
		if(tp==r[ts]+1) s[ts]=tv; else s[ts]=ts+2;
		tp=r[tv]-(tp-r[ts]-1)+1;ts+=2;
	}}
}
void build()
{
	ts=2;tp=0;tv=0;
	fill(r,r+MAX,n-1);
	l[0]=-1;r[0]=-1;l[1]=-1;r[1]=-1;s[0]=1;
	memset(t,-1,sizeof(t));
	fill(t[1],t[1]+MAX_C,0);
	for(i=0;i<n;i++) ukkadd(str[i]-'a');
}
dt dfs(ll tv,ll d)
{
	if(tv==-1)return {{0,0},0};
	if(r[tv]==n-1){
		if(l[tv]-d<n1)return {{1,0},0};
		if(l[tv]-d<n1+n2+1)return {{0,1},0};
		return {{0,0},1};
	}
	dt ans;
	for(ll i=0;i<MAX_C;i++){
		dt x=dfs(t[tv][i],d+r[tv]-l[tv]+1);
		ans={{(ans.fi.fi+x.fi.fi)%MOD,(ans.fi.se+x.fi.se)%MOD},(ans.se+x.se)%MOD};
	}
	ll y=(((ans.se*ans.fi.fi)%MOD)*ans.fi.se)%MOD;
	for(ll i=l[tv]; i>=0 && i<=r[tv];i++)cnt[d+i-l[tv]]=(cnt[d+i-l[tv]]+y)%MOD;
	return ans;
}
int main()
{
	boost;
	string str1,str2,str3;
	cin>>str1>>str2>>str3;
	n1=str1.length(),n2=str2.length(),n3=str3.length();
	str=str1;str+="|";str+=str2;str+="|";str+=str3;str+="{";
	n=str.length();
	build();
	dfs(0,-1);
	for(ll i=0;i<min(n1,min(n2,n3));i++)cout<<cnt[i]<<' ';
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MAX=1e6+5;
const ll MAX_C=28;
ll MOD=1e9+7;
ll MOD1=1e9+9;
#define pb push_back
#define se second
#define fi first
#define db double
#define pdb pair<db,db>
#define maxe max_element
#define mine min_element
#define debug(x) cout<<#x<<" :: "<<x<<endl;
#define debug2(x,y) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<endl;
#define debug3(x,y,z) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\t"<<#z<<" :: "<<z<<endl;
#define debug4(x,y,z,w) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\t"<<#z<<" :: "<<z<<"\t"<<#w<<" :: "<<w<<endl;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define fbo find_by_order
#define ook order_of_key
#define ub upper_bound
#define lb lower_bound
#define pq priority_queue
#define pll pair<ll,ll>
#define boost               ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
using namespace __gnu_pbds;
#define ordered_set tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update>
#define dt pair<pll,ll>
int t[MAX][MAX_C],s[MAX],l[MAX],r[MAX],p[MAX],ts,tv,tp,i,n,n1,n2,n3;
string str;
ll cnt[MAX];
void ukkadd(ll c)
{
	while(1){
	if(r[tv]<tp){
		if(t[tv][c]==-1){t[tv][c]=ts;l[ts]=i;p[ts++]=tv;tv=s[tv];tp=r[tv]+1;continue;}
		tv=t[tv][c];tp=l[tv];
	}
	if(tp==-1 || c==str[tp]-'a'){
		tp++;break;
	}
	else{
		l[ts]=l[tv];p[ts]=p[tv];r[ts]=tp-1;t[ts][str[tp]-'a']=tv;
		l[ts+1]=i;p[ts+1]=ts;t[ts][c]=ts+1;
		l[tv]=tp;p[tv]=ts;t[p[ts]][str[l[ts]]-'a']=ts;
		tv=s[p[ts]];tp=l[ts];
		while(tp<=r[ts]){tv=t[tv][str[tp]-'a'];tp+=r[tv]-l[tv]+1;}
		if(tp==r[ts]+1) s[ts]=tv; else s[ts]=ts+2;
		tp=r[tv]-(tp-r[ts]-1)+1;ts+=2;
	}}
}
void build()
{
	ts=2;tp=0;tv=0;
	fill(r,r+MAX,n-1);
	l[0]=-1;r[0]=-1;l[1]=-1;r[1]=-1;s[0]=1;
	memset(t,-1,sizeof(t));
	fill(t[1],t[1]+MAX_C,0);
	for(i=0;i<n;i++) ukkadd(str[i]-'a');
}
dt dfs(ll tv,ll d)
{
	if(tv==-1)return {{0,0},0};
	if(r[tv]==n-1){
		if(l[tv]-d<n1)return {{1,0},0};
		if(l[tv]-d<n1+n2+1)return {{0,1},0};
		return {{0,0},1};
	}
	dt ans={{0,0},0};
	for(ll i=0;i<MAX_C;i++){
		dt x=dfs(t[tv][i],d+r[tv]-l[tv]+1);
		ans={{(ans.fi.fi+x.fi.fi)%MOD,(ans.fi.se+x.fi.se)%MOD},(ans.se+x.se)%MOD};
	}
	ll y=(((ans.se*ans.fi.fi)%MOD)*ans.fi.se)%MOD;
	if(tv){
	cnt[d]=(cnt[d]+y)%MOD;
	cnt[d+r[tv]-l[tv]+1]=(cnt[d+r[tv]-l[tv]+1]-y+MOD)%MOD;}
	return ans;
}
int main()
{
	boost;
	string str1,str2,str3;
	cin>>str1>>str2>>str3;
	n1=str1.length(),n2=str2.length(),n3=str3.length();
	str=str1;str+="|";str+=str2;str+="|";str+=str3;str+="{";
	n=str.length();
	build();
	dfs(0,-1);
	for(ll i=1;i<min(n1,min(n2,n3));i++)cnt[i]=(cnt[i]+cnt[i-1])%MOD;
	for(ll i=0;i<min(n1,min(n2,n3));i++)cout<<cnt[i]<<' ';
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll MAX=1e6+5;
const ll MAX_C=28;
ll MOD=1e9+7;
ll MOD1=1e9+9;
#define pb push_back
#define se second
#define fi first
#define db double
#define pdb pair<db,db>
#define maxe max_element
#define mine min_element
#define debug(x) cout<<#x<<" :: "<<x<<endl;
#define debug2(x,y) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<endl;
#define debug3(x,y,z) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\t"<<#z<<" :: "<<z<<endl;
#define debug4(x,y,z,w) cout<<#x<<" :: "<<x<<"\t"<<#y<<" :: "<<y<<"\t"<<#z<<" :: "<<z<<"\t"<<#w<<" :: "<<w<<endl;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define fbo find_by_order
#define ook order_of_key
#define ub upper_bound
#define lb lower_bound
#define pq priority_queue
#define pll pair<ll,ll>
#define boost               ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
using namespace __gnu_pbds;
#define ordered_set tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update>
#define dt pair<pll,ll>
int t[MAX][MAX_C],s[MAX],l[MAX],r[MAX],p[MAX],ts,tv,tp,i,n,n1,n2,n3;
string str;
ll cnt[MAX];
void ukkadd(ll c)
{
	while(1){
	if(r[tv]<tp){
		if(t[tv][c]==-1){t[tv][c]=ts;l[ts]=i;p[ts++]=tv;tv=s[tv];tp=r[tv]+1;continue;}
		tv=t[tv][c];tp=l[tv];
	}
	if(tp==-1 || c==str[tp]-'a'){
		tp++;break;
	}
	else{
		l[ts]=l[tv];p[ts]=p[tv];r[ts]=tp-1;t[ts][str[tp]-'a']=tv;
		l[ts+1]=i;p[ts+1]=ts;t[ts][c]=ts+1;
		l[tv]=tp;p[tv]=ts;t[p[ts]][str[l[ts]]-'a']=ts;
		tv=s[p[ts]];tp=l[ts];
		while(tp<=r[ts]){tv=t[tv][str[tp]-'a'];tp+=r[tv]-l[tv]+1;}
		if(tp==r[ts]+1) s[ts]=tv; else s[ts]=ts+2;
		tp=r[tv]-(tp-r[ts]-1)+1;ts+=2;
	}}
}
void build()
{
	ts=2;tp=0;tv=0;
	fill(r,r+MAX,n-1);
	l[0]=-1;r[0]=-1;l[1]=-1;r[1]=-1;s[0]=1;
	memset(t,-1,sizeof(t));
	fill(t[1],t[1]+MAX_C,0);
	for(i=0;i<n;i++) ukkadd(str[i]-'a');
}
dt dfs(ll tv,ll d)
{
	if(tv==-1)return {{0,0},0};
	if(r[tv]==n-1){
		if(l[tv]-d<n1)return {{1,0},0};
		if(l[tv]-d<n1+n2+1)return {{0,1},0};
		return {{0,0},1};
	}
	dt ans={{0,0},0};
	for(ll i=0;i<MAX_C;i++){
		dt x=dfs(t[tv][i],d+r[tv]-l[tv]+1);
		ans={{(ans.fi.fi+x.fi.fi)%MOD,(ans.fi.se+x.fi.se)%MOD},(ans.se+x.se)%MOD};
	}
	ll y=(((ans.se*ans.fi.fi)%MOD)*ans.fi.se)%MOD;
	for(ll i=l[tv]; i>=0 && i<=r[tv];i++)cnt[d+i-l[tv]]=(cnt[d+i-l[tv]]+y)%MOD;
	return ans;
}
int main()
{
	boost;
	string str1,str2,str3;
	cin>>str1>>str2>>str3;
	n1=str1.length(),n2=str2.length(),n3=str3.length();
	str=str1;str+="|";str+=str2;str+="|";str+=str3;str+="{";
	n=str.length();
	build();
	dfs(0,-1);
	for(ll i=0;i<min(n1,min(n2,n3));i++)cout<<cnt[i]<<' ';
}


/* LittleFall : Hello! */
#include <bits/stdc++.h>
using namespace std; using ll = long long; inline int read();
const int M = 300016, MOD = 1000000007;

/*
对每个l，求有几个三元组(i1,i2,i3)，使得s1[i1, i1+l-1], s2[i2, i2+l-1], s3[i3, i3+l-1]相等
建立三元的后缀自动机，统计每个节点在三个字符串中的出现次数c1, c2, c3.
然后l在len[link[i]]+1, len[i]的范围内，都加上c1*c2*c3.
*/

int sz, lst; //后缀自动机大小，上一次插入的节点
int ch[M<<1][27], len[M<<1], link[M<<1], cnt[3][M<<1];

void extend(const char *s, int id)
{
	for(int i=0; s[i]; ++i)
	{
		int c = s[i]-'a';
		int cur = ++sz;
		len[cur] = len[lst] + 1;

		int p = lst;
		while(!ch[p][c])
		{
			ch[p][c] = cur;
			p = link[p];
		}
		if(ch[p][c] != cur)
		{
			int q = ch[p][c];
			if(len[p] + 1 == len[q]) link[cur] = q;
			else
			{
				int clone = ++sz;
				memcpy(ch[clone], ch[q], sizeof(ch[q]));
				link[clone] = link[q];
				len[clone] = len[p]+1;
				while(ch[p][c]==q)
				{
					ch[p][c] = clone;
					p = link[p];
				}
				link[q] = link[cur] = clone;
			}
		}
		lst = cur;
		if(s[i]!='{')
			++cnt[id][cur];
	}
}
void build()
{
	vector<int> nodes;
	for(int i=1; i<=sz; ++i)
		nodes.push_back(i);
	sort(nodes.begin(), nodes.end(), [&](int a, int b){
		return len[a]>len[b];
	});
	for(auto u:nodes)
		for(auto cntx:cnt)
		cntx[link[u]] += cntx[u];
}

char str[M];
ll ans[M];
void add(int l, int r, int v)
{
	ans[r+1] -= v;
	ans[l] += v;
}
int main(void)
{
	#ifdef _LITTLEFALL_
	freopen("in.txt","r",stdin);
    #endif

	int n = M;
	for(int i=0; i<3; ++i)
	{
		scanf("%s", str);
		n = min(n, (int)strlen(str));
		extend(str, i);
		extend("{", i);
	}
	build();
	for(int i=1; i<=sz; ++i)
		add(len[link[i]]+1, len[i], 1ll*cnt[0][i]*cnt[1][i]*cnt[2][i]%MOD);

	for(int i=1; i<=n; ++i)
	{
		ans[i] += ans[i-1];
		ans[i] = (ans[i] % MOD + MOD)%MOD;
		printf("%I64d ", ans[i]);
	}

    return 0;
}

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}


#include <bits/stdc++.h>
using namespace std;

#define int long long
#define sync ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define file freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout)
#define endl "\n"
#define ends " "
#define die(x) return cout << x << endl, 0
#define all(v) v.begin(), v.end()
#define sz(x) (int)(x.size())
#define debug(x) cerr << #x << ": " << x << endl
#define debugP(p) cerr << #p << ": {" << p.first << ", " << p.second << '}' << endl
#define debugV(v) cerr << #v << ": [ "; for(int __ = 0; __ < v.size(); __++) cerr << v[__] << ((__ != v.size() - 1) ? ", " : ends); cerr << ']' << endl
#define debugVP(v) cerr << #v << ": [ "; for(int ___ = 0; ___ < v.size(); ___++) cerr << '{' << v[___].first << ", " << v[___].second << '}' << ((___ != v.size() - 1) ? ", " : ends); cerr << ']' << endl
#define debugA(a, n) cerr << #a << ": [ "; for(int ____ = 0; ____ < n; ____++) cerr << a[____] << ((____ != n - 1) ? ", " : ends); cerr << ']' << endl
#define print(args...) fprintf (stderr, args)
typedef long long ll;
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef vector<pii> vpii;
const int INF = 1e9, MOD = INF + 7;

/////////////////////////////////////////////////////////////////////

const int N = 3e5 + 20, M = 20 + 1;

int n, rnk[M][N], suf[N], cnt[N][3], ans[N], par[N];
pii lc[N];

int lcp(int x, int y) {
	int l = 0;
	for(int i = M - 1; i >= 0 && x < n && y < n; i--) if (rnk[i][x] == rnk[i][y]) x += (1 << i), y += (1 << i), l += (1 << i);
	return l;
}

int getPar(int v) { return (par[v] == v ? v : par[v] = getPar(par[v])); }

void merge(int v, int u, int w) {
	v = getPar(v);
	u = getPar(u);
	ans[w] -= cnt[v][0] * cnt[v][1] * cnt[v][2];
	ans[w] -= cnt[u][0] * cnt[u][1] * cnt[u][2];
	par[u] = v;
	cnt[v][0] += cnt[u][0];
	cnt[v][1] += cnt[u][1];
	cnt[v][2] += cnt[u][2];
	ans[w] += cnt[v][0] * cnt[v][1] * cnt[v][2];
}

int32_t main() {

    sync;

	for(int i = 1; i < N; i++) par[i] = i;
	string s1, s2, s3; cin >> s1 >> s2 >> s3;
	string s  = s1 + '$' + s2 + '#' + s3;
	n = sz(s);
	for(int i = 0; i < n; i++) rnk[0][i] = s[i] - 'a';
	for(int i = 1; i < M; i++) {
		vector< pair<pii, int> > v;
		for(int j = 0; j < n; j++) {
			if (j + (1 << (i - 1)) < n) v.push_back(make_pair(make_pair(rnk[i - 1][j], rnk[i - 1][j + (1 << (i - 1))]), j));
			else v.push_back(make_pair(make_pair(rnk[i - 1][j], -1), j));
		}
		sort(all(v));
		for(int j = 1; j < n; j++) rnk[i][v[j].second] = rnk[i][v[j - 1].second] + (v[j].first != v[j - 1].first) ;
	}

	for(int i = 0; i < n; i++) suf[rnk[M - 1][i]] = i;
	for(int i = 0; i < n; i++) {
		if (s[suf[i]] == '$' || s[suf[i]] == '#') continue;
		if (suf[i] < sz(s1)) cnt[i][0]++;
		else if (suf[i] < sz(s1) + sz(s2) + 1) cnt[i][1]++;
		else cnt[i][2]++;
	}
	for(int i = 0; i < n - 1; i++) lc[i] = make_pair(lcp(suf[i], suf[i + 1]), i);
	sort(lc, lc + n - 1);
	reverse(lc, lc + n - 1);
	for(int i = 0; i < n - 1; i++) merge(lc[i].second, lc[i].second + 1, lc[i].first);
	for(int i = N - 1; i > 1; i--) ans[i - 1] += ans[i];

	for(int i = 1; i <= min(min(sz(s1), sz(s2)), sz(s3)); i++) cout << ans[i] % MOD << ends;

	return 0;
}


#include<string>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#include<deque>
#include<iomanip>
#include<sstream>
#include<stack>
#include<iostream>
#include<limits>
#include<bitset>
#include<list>
#include<queue>
#include<memory>
#include<functional>

#define For(n) for(int i=0;i<n;++i)
using namespace std;
const int N = 800010;
struct EXSAM_node
{
	EXSAM_node *next[26],*pre;
	//bitset<10> part;//属于哪个主串
	int step;
	int bel;
	int size;
	int visit;
	int cnt[3];
	void clear()
	{
		pre = NULL;
		step = 0;
		size = 0;
		visit = 0;
		memset(next, 0, sizeof(next));
		memset(cnt, 0, sizeof(cnt));
	}
};
EXSAM_node EXSAM_Pool[N * 2];
EXSAM_node *EXpool[N * 2];
long d[N * 2];
struct EXSAM
{
	EXSAM_node *root, *last;
	EXSAM_node  *cur;
	void init()
	{
		cur = EXSAM_Pool;  //cur=当前弧
		root = last = cur++;
		root->clear();
		root->visit = 0;
	}
	void Insert(int w,int i)//第i个子串的字符,每插入新串时last应设置为root
	{
		EXSAM_node *p = last;
		if (p->next[w] && p->next[w]->step == p->step + 1)
		{
			last = p->next[w];
			last->cnt[i]++;
			return;
		}
		EXSAM_node *np = cur++;
		np->clear();
		np->step = p->step + 1;
			while (p && !p->next[w])
			{
				p->next[w] = np, p = p->pre;
			}
			if (p == 0)
				np->pre = root;
			else
			{
				EXSAM_node *q = p->next[w];
				if (p->step + 1 == q->step)
					np->pre = q;
				else
				{
					EXSAM_node *nq = cur++;
					nq->clear();
					nq->step = p->step + 1;
					memcpy(nq->next, q->next, sizeof(q->next));
					nq->pre = q->pre;
					q->pre = nq;
					np->pre = nq;
					while (p&&p->next[w] == q)
					{
						p->next[w] = nq, p = p->pre;
					}
				}
			}
		last = np;
		last->cnt[i] = 1;
	}
	void topo()
	{
		// 求出parent树的拓扑序
		int cnt = cur - EXSAM_Pool;
		int maxVal = 0;
		memset(d, 0, sizeof(d));
		for (int i = 1; i < cnt; i++)
		{
			maxVal = max(maxVal, EXSAM_Pool[i].step), d[EXSAM_Pool[i].step]++;
		}
		for (int i = 1; i <= maxVal; i++)
			d[i] += d[i - 1];
		for (int i = 1; i < cnt; i++)
			EXpool[d[EXSAM_Pool[i].step]--] = &EXSAM_Pool[i];
		EXpool[0] = root;
	}
};
long long part10[500000];
const int mod1 = 1e9 + 7;
int main()
{
	ios::sync_with_stdio(false);
	EXSAM part;
	string a, b, c;
	cin.tie(0);
	cout.tie(0);
	cin >> a >> b >> c;
		part.init();
		for (auto &s : a)
			part.Insert(s - 'a', 0);
		part.last = part.root;
		for (auto &s : b)
			part.Insert(s - 'a', 1);
		part.last = part.root;
		for (auto &s : c)
			part.Insert(s - 'a', 2);
		part.topo();
		int pp = min(a.size(), min(b.size(), c.size()));
		int cnt = part.cur - EXSAM_Pool;
		for (int i = cnt - 1; i >= 1; i--)
		{
			EXpool[i]->pre->cnt[0] += EXpool[i]->cnt[0];
			EXpool[i]->pre->cnt[1] += EXpool[i]->cnt[1];
			EXpool[i]->pre->cnt[2] += EXpool[i]->cnt[2];
		}
		for (int i = 1; i <cnt; i++)
		{
			long long tmp = (long long)EXpool[i]->cnt[0] * EXpool[i]->cnt[1] * EXpool[i]->cnt[2];
			part10[EXpool[i]->pre->step] -= （tmp% 1000000007）;
			part10[EXpool[i]->step] +=（tmp% 1000000007）;
		}
		for (long i = pp-1; i >= 1; --i)
			part10[i] += part10[i+1] % 1000000007;
		for (long i = 1; i <= pp; ++i)
			cout << part10[i]% 1000000007 << " ";
	return 0;
}


#include<string>
#include<cstring>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#include<deque>
#include<iomanip>
#include<sstream>
#include<stack>
#include<iostream>
#include<limits>
#include<bitset>
#include<list>
#include<queue>
#include<memory>
#include<functional>

#define For(n) for(int i=0;i<n;++i)
using namespace std;
const int N = 800010;
struct EXSAM_node
{
	EXSAM_node *next[26],*pre;
	//bitset<10> part;//属于哪个主串
	int step;
	int bel;
	int size;
	int visit;
	int cnt[3];
	void clear()
	{
		pre = NULL;
		step = 0;
		size = 0;
		visit = 0;
		memset(next, 0, sizeof(next));
		memset(cnt, 0, sizeof(cnt));
	}
};
EXSAM_node EXSAM_Pool[N * 2];
EXSAM_node *EXpool[N * 2];
long d[N * 2];
struct EXSAM
{
	EXSAM_node *root, *last;
	EXSAM_node  *cur;
	void init()
	{
		cur = EXSAM_Pool;  //cur=当前弧
		root = last = cur++;
		root->clear();
		root->visit = 0;
	}
	void Insert(int w,int i)//第i个子串的字符,每插入新串时last应设置为root
	{
		EXSAM_node *p = last;
		if (p->next[w] && p->next[w]->step == p->step + 1)
		{
			last = p->next[w];
			last->cnt[i]++;
			return;
		}
		EXSAM_node *np = cur++;
		np->clear();
		np->step = p->step + 1;
			while (p && !p->next[w])
			{
				p->next[w] = np, p = p->pre;
			}
			if (p == 0)
				np->pre = root;
			else
			{
				EXSAM_node *q = p->next[w];
				if (p->step + 1 == q->step)
					np->pre = q;
				else
				{
					EXSAM_node *nq = cur++;
					nq->clear();
					nq->step = p->step + 1;
					memcpy(nq->next, q->next, sizeof(q->next));
					nq->pre = q->pre;
					q->pre = nq;
					np->pre = nq;
					while (p&&p->next[w] == q)
					{
						p->next[w] = nq, p = p->pre;
					}
				}
			}
		last = np;
		last->cnt[i] = 1;
	}
	void topo()
	{
		// 求出parent树的拓扑序
		int cnt = cur - EXSAM_Pool;
		int maxVal = 0;
		memset(d, 0, sizeof(d));
		for (int i = 1; i < cnt; i++)
		{
			maxVal = max(maxVal, EXSAM_Pool[i].step), d[EXSAM_Pool[i].step]++;
		}
		for (int i = 1; i <= maxVal; i++)
			d[i] += d[i - 1];
		for (int i = 1; i < cnt; i++)
			EXpool[d[EXSAM_Pool[i].step]--] = &EXSAM_Pool[i];
		EXpool[0] = root;
	}
};
long long part10[500000];
const int mod1 = 1e9 + 7;
int main()
{
	ios::sync_with_stdio(false);
	EXSAM part;
	string a, b, c;
	cin.tie(0);
	cout.tie(0);
	cin >> a >> b >> c;
		part.init();
		for (auto &s : a)
			part.Insert(s - 'a', 0);
		part.last = part.root;
		for (auto &s : b)
			part.Insert(s - 'a', 1);
		part.last = part.root;
		for (auto &s : c)
			part.Insert(s - 'a', 2);
		part.topo();
		int pp = min(a.size(), min(b.size(), c.size()));
		int cnt = part.cur - EXSAM_Pool;
		for (int i = cnt - 1; i >= 1; i--)
		{
			EXpool[i]->pre->cnt[0] += EXpool[i]->cnt[0];
			EXpool[i]->pre->cnt[1] += EXpool[i]->cnt[1];
			EXpool[i]->pre->cnt[2] += EXpool[i]->cnt[2];
		}
		for (int i = 1; i <cnt; i++)
		{
			part10[EXpool[i]->step] += (long long)(((long long)EXpool[i]->cnt[0]) * ((long long)EXpool[i]->cnt[1]) * ((long long)EXpool[i]->cnt[2]));
			part10[EXpool[i]->pre->step] -= (long long)(((long long)EXpool[i]->cnt[0]) * ((long long)EXpool[i]->cnt[1]) * ((long long)EXpool[i]->cnt[2]));
			//long long tmp = (long long)EXpool[i]->cnt[0] * EXpool[i]->cnt[1] * EXpool[i]->cnt[2];
			//part10[EXpool[i]->pre->step] -= tmp;
			//part10[EXpool[i]->step] +=tmp;
		}
		for (long i = pp-1; i >= 1; --i)
			part10[i] += part10[i+1] % 1000000007;
		for (long i = 1; i <= pp; ++i)
			cout << part10[i]% 1000000007 << " ";
	return 0;
}