#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
#include <cstring>
#include <climits>
#include <algorithm>
#include <map>
#include <set>
#include <cstdlib>
#include <iterator>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

int n,m,W,k,schw,schc;
int a[2000],b[2000];
bool b1[2000];
int dp[2000][2000];
vector<vector<int> > g,ans;
vector<pair<int,int> > sum(1);

void dfs(int x)
{
    ans[k].push_back(x);
    schw+=a[x];
    schc+=b[x];
    for (int i=0;i<g[x].size();i++)
    {
        if (!b1[g[x][i]])
        {
            b1[g[x][i]]=true;
            dfs(g[x][i]);
        }
    }
}

int main()
{
    ios_base::sync_with_stdio(false);
    #ifdef LOCAL
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    #endif

    cin>>n>>m>>W;
    g.resize(n+1); ans.resize(n+1);
    for (int i=1;i<=n;i++) cin>>a[i];
    for (int i=1;i<=n;i++) cin>>b[i];

    for (int i=1;i<=m;i++)
    {
        int x,y;
        cin>>x>>y;
        g[x].push_back(y);
        g[y].push_back(x);
    }

    for (int i=1;i<=n;i++)
    {
        if (!b1[i])
        {
            k++;
            b1[i]=true;
            dfs(i);
            sum.push_back(make_pair(schw,schc));
           /* for (int i=0;i<ans[k].size();i++)
                cout<<ans[k][i]<<" ";
            cout<<endl;*/
            schw=schc=0;
        }
    }
    for (int i=1;i<=k;i++)
    {
        for (int j=1;j<=W;j++)
        {
            for (int j1=0;j1<ans[i].size();j1++)

                if (a[ans[i][j1]]<=j)
                dp[i][j]=max(max(dp[i-1][j],dp[i][j]),dp[i-1][j-a[ans[i][j1]]]+b[ans[i][j1]]);
                else dp[i][j]=max(dp[i-1][j],dp[i][j]);

            if (sum[i].first<=j)
                dp[i][j]=max(max(dp[i][j],dp[i-1][j]),dp[i-1][j-sum[i].first]+sum[i].second);
            else
                dp[i][j]=max(dp[i][j],dp[i-1][j]);

        }
    }
/*
    for (int i=1;i<=k;i++)
    {
        for (int j=1;j<=W;j++)
            cout<<dp[i][j]<<" ";
        cout<<endl;
    }*/

    cout<<dp[k][W];
    return 0;
  }


#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
vector <int> v[N];
vector <pair <int, int> > all[N];
int w[N], b[N], ww, n, m, wsum, bsum, d[N][N], p[N];
pair <int, int> best[N];
bool mark[N];
vector <pair <int, int> > check;

void dfs (int s, int id)
{
	mark[s] = true;
	all[id].push_back (make_pair (b[s], w[s]));
	wsum += w[s];
	bsum += b[s];
	for (int i = 0; i < v[s].size(); ++i)
		if (!mark[v[s][i]])
			dfs (v[s][i], id);
}

bool cmp (pair <int, int> aa, pair <int, int> bb )
{
	return aa.second < bb.second;
}

void update (int now, int limit)
{
	while (all[now][p[now]].second <= limit)
	{
		p[now]++;
		if (best[now].first < all[now][p[now]].first)
		{
			best[now] = all[now][p[now]];
			continue;
		}
		if (best[now].first > all[now][p[now]].first)
			continue;

		best[now].second = min (best[now].second, all[now][p[now]].second);
	}
}

int main()
{
	cin >> n >> m >> ww;
	for (int i = 1; i < n+1; ++i)
		cin >> w[i];
	for (int i = 1; i < n+1; ++i)
		cin >> b[i];

	int from, too;
	for (int i = 0; i < m; ++i)
	{
		cin >> from >> too;
		v[from].push_back (too);
		v[too].push_back (from);
	}

	int now = 0;

	for (int i = 1; i < n+1; ++i)
		if (!mark[i])
		{
			wsum = bsum = 0;
			all[now].push_back (make_pair (0, 0));
			all[now].push_back (make_pair (0, 1e8));
			dfs (i, now);
			check.push_back (make_pair (bsum, wsum));
			now ++;
		}

	for (int i = 0; i < now; ++i)
		sort (all[i].begin(), all[i].end(), cmp);

	for (int i = 0; i < ww+1; ++i)
	{
		update (0, i);
		d[0][i] = best[0].first;
		if (check[0].second <= i)
			d[0][i] = max (d[0][i], check[0].first);
	}

	for (int i = 0; i < check.size(); ++i)
		for (int j = 0; j < ww+1; ++j)
		{
			update (i, j);
			d[i][j] = d[i-1][j];
			if (j >= check[i].second)
				d[i][j] = max (d[i][j], (d[i-1][j-check[i].second] + check[i].first));
			d[i][j] = max (d[i][j], d[i-1][j-best[i].second]+best[i].first);
		}

	cout << d[check.size()-1][ww] << endl;

}


#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
vector <int> v[N];
vector <pair <int, int> > all[N];
int w[N], b[N], ww, n, m, wsum, bsum, d[N][N], p[N];
pair <int, int> best[N];
bool mark[N];
vector <pair <int, int> > check;

void dfs (int s, int id)
{
	mark[s] = true;
	all[id].push_back (make_pair (b[s], w[s]));
	wsum += w[s];
	bsum += b[s];
	for (int i = 0; i < v[s].size(); ++i)
		if (!mark[v[s][i]])
			dfs (v[s][i], id);
}

bool cmp (pair <int, int> aa, pair <int, int> bb )
{
	return aa.second < bb.second;
}

void update (int now, int limit)
{
	while (all[now][p[now]].second <= limit)
	{
		p[now]++;
		if (best[now].first < all[now][p[now]].first)
		{
			best[now] = all[now][p[now]];
			continue;
		}
		if (best[now].first > all[now][p[now]].first)
			continue;

		best[now].second = min (best[now].second, all[now][p[now]].second);
	}
}

int main()
{
	cin >> n >> m >> ww;
	for (int i = 1; i < n+1; ++i)
		cin >> w[i];
	for (int i = 1; i < n+1; ++i)
		cin >> b[i];

	int from, too;
	for (int i = 0; i < m; ++i)
	{
		cin >> from >> too;
		v[from].push_back (too);
		v[too].push_back (from);
	}

	int now = 0;

	for (int i = 1; i < n+1; ++i)
		if (!mark[i])
		{
			wsum = bsum = 0;
			all[now].push_back (make_pair (0, 0));
			all[now].push_back (make_pair (0, 1e8));
			dfs (i, now);
			check.push_back (make_pair (bsum, wsum));
			now ++;
		}

	for (int i = 0; i < now; ++i)
		sort (all[i].begin(), all[i].end(), cmp);

	for (int i = 0; i < ww+1; ++i)
	{
		update (0, i);
		d[0][i] = best[0].first;
		if (check[0].second <= i)
			d[0][i] = max (d[0][i], check[0].first);
	}

	for (int i = 1; i < check.size(); ++i)
		for (int j = 0; j < ww+1; ++j)
		{
			update (i, j);
			d[i][j] = d[i-1][j];
			if (j >= check[i].second)
				d[i][j] = max (d[i][j], (d[i-1][j-check[i].second] + check[i].first));
			d[i][j] = max (d[i][j], d[i-1][j-best[i].second]+best[i].first);
		}

	cout << d[check.size()-1][ww] << endl;

}


#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
vector <int> v[N];
vector <pair <int, int> > all[N];
int w[N], b[N], ww, n, m, wsum, bsum, d[N][N], p[N];
pair <int, int> best[N];
bool mark[N];
vector <pair <int, int> > check;

void dfs (int s, int id)
{
	mark[s] = true;
	all[id].push_back (make_pair (b[s], w[s]));
	wsum += w[s];
	bsum += b[s];
	for (int i = 0; i < v[s].size(); ++i)
		if (!mark[v[s][i]])
			dfs (v[s][i], id);
}

bool cmp (pair <int, int> aa, pair <int, int> bb )
{
	return aa.second < bb.second;
}

void update (int now, int limit)
{
	while (all[now][p[now]+1].second <= limit)
	{
		p[now]++;
		if (best[now].first < all[now][p[now]].first)
		{
			best[now] = all[now][p[now]];
			continue;
		}
		if (best[now].first > all[now][p[now]].first)
			continue;

		best[now].second = min (best[now].second, all[now][p[now]].second);
	}
}

int main()
{
	cin >> n >> m >> ww;
	for (int i = 1; i < n+1; ++i)
		cin >> w[i];
	for (int i = 1; i < n+1; ++i)
		cin >> b[i];

	int from, too;
	for (int i = 0; i < m; ++i)
	{
		cin >> from >> too;
		v[from].push_back (too);
		v[too].push_back (from);
	}

	int now = 0;

	for (int i = 1; i < n+1; ++i)
		if (!mark[i])
		{
			wsum = bsum = 0;
			all[now].push_back (make_pair (0, 0));
			all[now].push_back (make_pair (0, 1e8));
			dfs (i, now);
			check.push_back (make_pair (bsum, wsum));
			now ++;
		}

	for (int i = 0; i < now; ++i)
		sort (all[i].begin(), all[i].end(), cmp);

	for (int i = 0; i < ww+1; ++i)
	{
		update (0, i);
		d[0][i] = best[0].first;
		if (check[0].second <= i)
			d[0][i] = max (d[0][i], check[0].first);
	}

	for (int i = 1; i < check.size(); ++i)
		for (int j = 1; j < ww+1; ++j)
		{
			update (i, j);
			d[i][j] = d[i-1][j];
			if (j >= check[i].second)
				d[i][j] = max (d[i][j], (d[i-1][j-check[i].second] + check[i].first));
			d[i][j] = max (d[i][j], d[i-1][j-best[i].second]+best[i].first);
		}

	cout << d[check.size()-1][ww] << endl;

}


#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
vector <int> v[N];
vector <pair <int, int> > all[N];
int w[N], b[N], ww, n, m, wsum, bsum, d[N][N], p[N];
pair <int, int> best[N];
bool mark[N];
vector <pair <int, int> > check;

void dfs (int s, int id)
{
	mark[s] = true;
	all[id].push_back (make_pair (b[s], w[s]));
	wsum += w[s];
	bsum += b[s];
	for (int i = 0; i < v[s].size(); ++i)
		if (!mark[v[s][i]])
			dfs (v[s][i], id);
}

bool cmp (pair <int, int> aa, pair <int, int> bb )
{
	return aa.second < bb.second;
}

void update (int now, int limit)
{
	while (all[now][p[now]].second <= limit)
	{
		p[now]++;
		if (best[now].first < all[now][p[now]].first)
		{
			best[now] = all[now][p[now]];
			continue;
		}
		if (best[now].first > all[now][p[now]].first)
			continue;

		best[now].second = min (best[now].second, all[now][p[now]].second);
	}
}

int main()
{
	cin >> n >> m >> ww;
	for (int i = 1; i < n+1; ++i)
		cin >> w[i];
	for (int i = 1; i < n+1; ++i)
		cin >> b[i];

	int from, too;
	for (int i = 0; i < m; ++i)
	{
		cin >> from >> too;
		v[from].push_back (too);
		v[too].push_back (from);
	}

	int now = 0;

	for (int i = 1; i < n+1; ++i)
		if (!mark[i])
		{
			wsum = bsum = 0;
			all[now].push_back (make_pair (0, 0));
			all[now].push_back (make_pair (0, 1e8));
			dfs (i, now);
			check.push_back (make_pair (bsum, wsum));
			now ++;
		}

	for (int i = 0; i < now; ++i)
		sort (all[i].begin(), all[i].end(), cmp);

	for (int i = 0; i < check.size(); ++i)
		for (int j = 0; j < ww+1; ++j)
		{
			update (i, j);
			if (i == 0)
			{
				d[i][j] = best[i].first;
				continue;
			}
			d[i][j] = d[i-1][j];
			if (j >= check[i].second)
				d[i][j] = max (d[i][j], (d[i-1][j-check[i].second] + check[i].first));
			d[i][j] = max (d[i][j], d[i-1][j-best[i].second]+best[i].first);
		}

	cout << d[check.size()-1][ww] << endl;

}


#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
int n, m, d[N][N], b[N], w[N], ww;
vector <int> v[N];
bool mark[N];
int allw, allb, now, ans;

void dfs (int st)
{
	mark[st] = true;

	for (int i = w[st]; i < ww+1; ++i)
	{
		d[now][i] = max (d[now][i], d[now-1][i-w[st]]+b[st]);
		ans = max (ans, d[now][i]);
	}

	allw += w[st];
	allb += b[st];

	for (int i = 0; i < v[st].size(); ++i)
		if (!mark[v[st][i]])
			dfs (v[st][i]);
}

int main()
{
	cin >> n >> m >> ww;
	int x, u;
	for (int i = 1; i < n+1; ++i)
		scanf ("%d", w+i);
	for (int i = 1; i < n+1; ++i)
		scanf ("%d", b+i);

	for (int i = 0; i < m; ++i)
	{
		scanf ("%d%d", &x, &u);
		v[x].push_back (u);
		v[u].push_back (x);
	}

	now = 1;

	for (int i = 1; i < n+1; ++i)
		if (!mark[i])
		{
			allw = 0;
			allb = 0;
			dfs (i);
			for (int j = allw; j < ww+1; ++j)
			{
				d[now][j] = max (d[now][j], d[now-1][j-allw]+allb);
				ans = max (ans, d[now][j]);
			}
			now++;
			for (int j = 0; j < ww+1; ++j)
				d[now][j] = d[now-1][j];
		}

	cout << ans << endl;

}


//8:51
//9:00
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3+10;
int n, m, d[N][N], b[N], w[N], ww;
vector <int> v[N];
bool mark[N];
int allw, allb, now;

void dfs (int st)
{
	mark[st] = true;

	for (int i = w[st]; i < ww+1; ++i)
		d[now][i] = max (d[now][i], d[now-1][i-w[st]]+b[st]);

	allw += w[st];
	allb += b[st];

	for (int i = 0; i < v[st].size(); ++i)
		if (!mark[v[st][i]])
			dfs (v[st][i]);
}

int main()
{
	cin >> n >> m >> ww;
	int x, u;
	for (int i = 1; i < n+1; ++i)
		scanf ("%d", w+i);
	for (int i = 1; i < n+1; ++i)
		scanf ("%d", b+i);

	for (int i = 0; i < m; ++i)
	{
		scanf ("%d%d", &x, &u);
		v[x].push_back (u);
		v[u].push_back (x);
	}

	now = 1;

	for (int i = 1; i < n+1; ++i)
		if (!mark[i])
		{
			allw = allb = 0;
			dfs (i);
			for (int j = allw; j < ww+1; ++j)
				d[now][j] = max (d[now][j], d[now-1][j-allw]+allb);
			now++;
		}

	int maa = 0;
	for (int j = 1; j < now; ++j)
		for (int i = ww; i > -1; --i)
			maa = max (maa, d[j][i]);
	cout << maa;

}


#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<stack>

using namespace std;

#define sd(x) scanf("%d",&x);
#define LL long long
#define LD long double
#define PB push_back
#define MP make_pair
#define F first
#define S second
#define Fill(a, b) memset(a, b, sizeof(a))
#define INF 2000000009

typedef pair<int,int> PII;
typedef vector<int> VI;

#define MAXN 300010
#define MAXLG 22
#define INF 1000000009

int mod=1000000007;

int tree1[MAXN],tree2[MAXN],tree3[MAXN],x,y,ma[MAXN][MAXLG],l,last[MAXN],idx[MAXN];

LL ans[MAXN];

void update(int idx ,int val,int tree[])
{
	while (idx <= MAXN)
    {
		tree[idx] += val;
		idx += (idx & -idx);
	}
}
int read(int idx,int tree[])
{
	int sum = 0;
	while (idx > 0)
    {
		sum += tree[idx];
		idx -= (idx & -idx);
	}
	return sum;
}

struct entry
{
    int nr[2];
    int p;
} L[MAXN];

int P[MAXLG][MAXN];
int N,i;
int stp, cnt,ar[MAXN],comp[MAXN];

int cmp(entry a, entry b)
{
    if (a.nr[0]!=b.nr[0]) return a.nr[0]<b.nr[0];
    else return a.nr[1]<b.nr[1];
}

vector <entry > temp[MAXN];

void cnt_sort(int N)
{
	int curr=0;
	for(int i=0;i<N;i++)
	{
		if(L[i].nr[1]>-1)temp[L[i].nr[1]].PB(L[i]);
		else {L[curr]=L[i];curr++;}
	}
	for(int i=0;i<max(N,32);i++)
	{
		int l=temp[i].size();
		for(int j=0;j<l;j++)
		{
			L[curr]=temp[i][j];curr++;

		}
		temp[i].clear();

	}
	//cout<<"amana "<<curr<<endl;
	curr=0;
	for(int i=0;i<N;i++)
	{
		if(L[i].nr[0]>-1)temp[L[i].nr[0]].PB(L[i]);
		else {L[curr]=L[i];curr++;}
	}
	for(int i=0;i<max(N,32);i++)
	{
		int l=temp[i].size();
		for(int j=0;j<l;j++)
		{
			L[curr]=temp[i][j];curr++;
		}
		temp[i].clear();
	}//cout<<"aman "<<curr<<endl;
}

int FindLCP (int x,int y)
{
    int ans = 0 , k=0 , tmp=cnt;
    for (k=stp-1;k>= 0;k--,tmp>>=1)
    {
        if (x+tmp <= N && y+tmp <= N && P[k][x] == P[k][y])
        {// sort-index is same if the first k characters are same
            ans += tmp;
            // now we wish to find the characters that are same in the remaining strings
            x += tmp;
            y += tmp;
		}
	}
	return ans;
}

int rmq(int x,int y)
{
    int n=y-x+1,i=x,j=0,ans=x;
    while(n)
    {
        if(n&1)
        {
            if(ar[ans]>ar[ma[i][j]])ans=ma[i][j];
            i=i+(1<<j);
        }
        n>>=1;
        j++;

    }
    return ans;
}

void bin(int a,int b)
{
	if(a>=b)return;
	int mid=rmq(a,b);
	if(ar[mid]>l)return;
	LL x=read(b+1,tree1)-read(a-1,tree1);
	LL y=read(b+1,tree2)-read(a-1,tree2);
	LL z=read(b+1,tree3)-read(a-1,tree3);//cout<<a<<b<<mid<<x<<y<<z<<" "<<ar[mid]<<" "<<x*y*z<<endl;
	if(ar[mid]>last[a])
	{   //if(ar[mid]==3)cout<<a<<" "<<b<<mid<<x<<y<<z<<" "<<ar[mid]<<" "<<x*y*z<<endl;
		x=(x*y*z)%mod;
		ans[ar[mid]]+=x;
		ans[last[a]]-=x;
	}
	last[a]=ar[mid];
	last[mid+1]=ar[mid];
	bin(a,mid-1);
	bin(mid+1,b);
}

void solve()
{
    for(stp=1, cnt = 1; cnt < N; stp++, cnt *= 2)
    {
        for(i=0; i < N; i++)
        {
            L[i].nr[0]=P[stp- 1][i];
            L[i].nr[1]=i +cnt <N? P[stp -1][i+ cnt]:-1;
            L[i].p= i;
        }
        cnt_sort(N);
        //sort(L, L+N, cmp);
        for(i=0; i < N; i++)
            P[stp][L[i].p] =(((i> 0) && (L[i].nr[0]==L[i-1].nr[0]) && (L[i].nr[1] == L[i- 1].nr[1])) ? P[stp][L[i-1].p] : i);
    }
    //long long ans=N;
    //ans=(ans*(ans+1))/2;
    for(int i=0;i<N;i++)
    {
		if(i<=x)idx[i]=1;
		else if(i<=y)idx[i]=2;
		else idx[i]=3;
    }
    for(int i=0;i<N-1;i++)
    {
		ar[i]=FindLCP(L[i].p,L[i+1].p);
		//cout<<i<<" "<<ar[i]<<endl;
    }
    for(int i=0;i<N;i++)
    {
		if(L[i].p>y)update(i,1,tree3);
		else if(L[i].p>x&&L[i].p<y)update(i,1,tree2);
		else if(L[i].p<x)update(i,1,tree1);
		ma[i][0]=i;
    }

    for(int j=1;(1<<j)<=N;j++)
    {
        for(int i=0;(i+(1<<j))<=N-1;i++)
        {
            if(ar[ma[i][j-1]]<ar[ma[i+(1<<(j-1))][j-1]])
            {
                ma[i][j]=ma[i][j-1];
            }
            else ma[i][j]=ma[i+(1<<(j-1))][j-1];
        }
    }//cout<<"aman "<<N<<endl;
    bin(2,N-2);
    for(int i=l-1;i>=1;i--)
    {//cout<<ans[i]<<endl;
		ans[i]+=ans[i+1];
		ans[i]%=mod;
    }
    for(int i=1;i<=l;i++)
    {
		if(i!=1)cout<<" ";
		cout<<ans[i];
    }
    cout<<endl;

}
int main()
{
	int t=1,tmp,last;
	string a,b,c,s;
	//scanf("%d",&t);
	while(t--)
	{
		cin>>a>>b>>c;
		x=a.length();
		l=min(min(a.length(),b.length()),c.length());
		y=x+b.length()+1;
		s=a+"&"+b+"$"+c;
		N=s.length();
		for(int i=0;i<N;i++)P[0][i] = s[i]-97;
		solve();
	}
}


#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<stack>

using namespace std;

#define sd(x) scanf("%d",&x);
#define LL long long
#define LD long double
#define PB push_back
#define MP make_pair
#define F first
#define S second
#define Fill(a, b) memset(a, b, sizeof(a))
#define INF 2000000009

typedef pair<int,int> PII;
typedef vector<int> VI;

#define MAXN 300010
#define MAXLG 22
#define INF 1000000009

int mod=1000000007;

int tree1[MAXN],tree2[MAXN],tree3[MAXN],x,y,ma[MAXN][MAXLG],l,last=0;

LL ans[MAXN];

void update(int idx ,int val,int tree[])
{
	while (idx <= MAXN)
    {
		tree[idx] += val;
		idx += (idx & -idx);
	}
}
int read(int idx,int tree[])
{
	int sum = 0;
	while (idx > 0)
    {
		sum += tree[idx];
		idx -= (idx & -idx);
	}
	return sum;
}

struct entry
{
    int nr[2];
    int p;
} L[MAXN];

int P[MAXLG][MAXN];
int N,i;
int stp, cnt,ar[MAXN],comp[MAXN];

int cmp(entry a, entry b)
{
    if (a.nr[0]!=b.nr[0]) return a.nr[0]<b.nr[0];
    else return a.nr[1]<b.nr[1];
}

int FindLCP (int x,int y)
{
    int ans = 0 , k=0 , tmp=cnt;
    for (k=stp-1;k>= 0;k--,tmp>>=1)
    {
        if (x+tmp <= N && y+tmp <= N && P[k][x] == P[k][y])
        {// sort-index is same if the first k characters are same
            ans += tmp;
            // now we wish to find the characters that are same in the remaining strings
            x += tmp;
            y += tmp;
		}
	}
	return ans;
}

int rmq(int x,int y)
{
    int n=y-x+1,i=x,j=0,ans=x;
    while(n)
    {
        if(n&1)
        {
            if(ar[ans]>ar[ma[i][j]])ans=ma[i][j];
            i=i+(1<<j);
        }
        n>>=1;
        j++;

    }
    return ans;
}

void bin(int a,int b)
{
	if(a>=b)return;
	int mid=rmq(a,b);
	LL x=read(b+1,tree1)-read(a-1,tree1);
	LL y=read(b+1,tree2)-read(a-1,tree2);
	LL z=read(b+1,tree3)-read(a-1,tree3);//cout<<a<<b<<mid<<x<<y<<z<<" "<<ar[mid]<<" "<<x*y*z<<endl;
	if(ar[mid]!=last)
	{
		ans[ar[mid]]=(ans[ar[mid]]+(x*y*z))%mod;
		last=ar[mid];
	}
	bin(a,mid-1);
	bin(mid+1,b);
}

void solve()
{
    for(stp=1, cnt = 1; cnt < N; stp++, cnt *= 2)
    {
        for(i=0; i < N; i++)
        {
            L[i].nr[0]=P[stp- 1][i];
            L[i].nr[1]=i +cnt <N? P[stp -1][i+ cnt]:-1;
            L[i].p= i;
        }
        sort(L, L+N, cmp);
        for(i=0; i < N; i++)
            P[stp][L[i].p] =(((i> 0) && (L[i].nr[0]==L[i-1].nr[0]) && (L[i].nr[1] == L[i- 1].nr[1])) ? P[stp][L[i-1].p] : i);
    }
    //long long ans=N;
    //ans=(ans*(ans+1))/2;
    for(int i=0;i<N-1;i++)
    {
		ar[i]=FindLCP(L[i].p,L[i+1].p);
		//cout<<ar[i]<<endl;
    }
    for(int i=0;i<N;i++)
    {
		if(L[i].p>y)update(i,1,tree3);
		else if(L[i].p>x&&L[i].p<y)update(i,1,tree2);
		else if(L[i].p<x)update(i,1,tree1);
		ma[i][0]=i;
    }

    for(int j=1;(1<<j)<=N-1;j++)
    {
        for(int i=0;(i+(1<<j))<=N-1;i++)
        {
            if(ar[ma[i][j-1]]<ar[ma[i+(1<<(j-1))][j-1]])
            {
                ma[i][j]=ma[i][j-1];
            }
            else ma[i][j]=ma[i+(1<<(j-1))][j-1];
        }
    }//cout<<"aman "<<N<<endl;
    bin(2,N-2);
    for(int i=1;i<=l;i++)
    {
		if(i!=1)cout<<" ";
		cout<<ans[i];
    }
    cout<<endl;

}
int main()
{
	int t=1,tmp,last;
	string a,b,c,s;
	//scanf("%d",&t);
	while(t--)
	{
		cin>>a>>b>>c;
		x=a.length();
		l=min(min(a.length(),b.length()),c.length());
		y=x+b.length()+1;
		s=a+"&"+b+"$"+c;
		N=s.length();
		for(int i=0;i<N;i++)P[0][i] = s[i];
		solve();
	}
}


#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<stack>

using namespace std;

#define sd(x) scanf("%d",&x);
#define LL long long
#define LD long double
#define PB push_back
#define MP make_pair
#define F first
#define S second
#define Fill(a, b) memset(a, b, sizeof(a))
#define INF 2000000009

typedef pair<int,int> PII;
typedef vector<int> VI;

#define MAXN 300010
#define MAXLG 22
#define INF 1000000009

int mod=1000000007;

int tree1[MAXN],tree2[MAXN],tree3[MAXN],x,y,ma[MAXN][MAXLG],l,last[MAXN],idx[MAXN];

LL ans[MAXN];

void update(int idx ,int val,int tree[])
{
	while (idx <= MAXN)
    {
		tree[idx] += val;
		idx += (idx & -idx);
	}
}
int read(int idx,int tree[])
{
	int sum = 0;
	while (idx > 0)
    {
		sum += tree[idx];
		idx -= (idx & -idx);
	}
	return sum;
}

struct entry
{
    int nr[2];
    int p;
} L[MAXN];

int P[MAXLG][MAXN];
int N,i;
int stp, cnt,ar[MAXN],comp[MAXN];

int cmp(entry a, entry b)
{
    if (a.nr[0]!=b.nr[0]) return a.nr[0]<b.nr[0];
    else return a.nr[1]<b.nr[1];
}

vector <entry > temp[MAXN];

void cnt_sort(int N)
{
	int curr=0;
	for(int i=0;i<N;i++)
	{
		if(L[i].nr[1]!=-1)temp[L[i].nr[1]].PB(L[i]);
		else {L[curr]=L[i];curr++;}
	}
	for(int i=0;i<max(N,200);i++)
	{
		int l=temp[i].size();
		for(int j=0;j<l;j++)
		{
			L[curr]=temp[i][j];curr++;

		}
		temp[i].clear();

	}
	//cout<<"amana "<<curr<<endl;
	curr=0;
	for(int i=0;i<N;i++)
	{
		if(L[i].nr[0]!=-1)temp[L[i].nr[0]].PB(L[i]);
		else {L[curr]=L[i];curr++;}
	}
	for(int i=0;i<max(N,200);i++)
	{
		int l=temp[i].size();
		for(int j=0;j<l;j++)
		{
			L[curr]=temp[i][j];curr++;
		}
		temp[i].clear();
	}//cout<<"aman "<<curr<<endl;
}

int FindLCP (int x,int y)
{
    int ans = 0 , k=0 , tmp=cnt;
    for (k=stp-1;k>= 0;k--,tmp>>=1)
    {
        if (x+tmp <= N && y+tmp <= N && P[k][x] == P[k][y])
        {// sort-index is same if the first k characters are same
            ans += tmp;
            // now we wish to find the characters that are same in the remaining strings
            x += tmp;
            y += tmp;
		}
	}
	return ans;
}

int rmq(int x,int y)
{
    int n=y-x+1,i=x,j=0,ans=x;
    while(n)
    {
        if(n&1)
        {
            if(ar[ans]>ar[ma[i][j]])ans=ma[i][j];
            i=i+(1<<j);
        }
        n>>=1;
        j++;

    }
    return ans;
}

void bin(int a,int b)
{
	if(a>=b)return;
	int mid=rmq(a,b);
	if(ar[mid]>l)return;
	LL x=read(b+1,tree1)-read(a-1,tree1);
	LL y=read(b+1,tree2)-read(a-1,tree2);
	LL z=read(b+1,tree3)-read(a-1,tree3);//cout<<a<<b<<mid<<x<<y<<z<<" "<<ar[mid]<<" "<<x*y*z<<endl;
	if(ar[mid]>last[a])
	{   //if(ar[mid]==3)cout<<a<<" "<<b<<mid<<x<<y<<z<<" "<<ar[mid]<<" "<<x*y*z<<endl;
		x=(x*y*z)%mod;
		ans[ar[mid]]+=x;
		ans[last[a]]-=x;
	}
	last[a]=ar[mid];
	last[mid+1]=ar[mid];
	bin(a,mid-1);
	bin(mid+1,b);
}

void solve()
{
    for(stp=1, cnt = 1; cnt < N; stp++, cnt *= 2)
    {
        for(i=0; i < N; i++)
        {
            L[i].nr[0]=P[stp- 1][i];
            L[i].nr[1]=i +cnt <N? P[stp -1][i+ cnt]:-1;
            L[i].p= i;
        }
        cnt_sort(N);
        //sort(L, L+N, cmp);
        for(i=0; i < N; i++)
            P[stp][L[i].p] =(((i> 0) && (L[i].nr[0]==L[i-1].nr[0]) && (L[i].nr[1] == L[i- 1].nr[1])) ? P[stp][L[i-1].p] : i);
    }
    //long long ans=N;
    //ans=(ans*(ans+1))/2;
    for(int i=0;i<N;i++)
    {
		if(i<=x)idx[i]=1;
		else if(i<=y)idx[i]=2;
		else idx[i]=3;
    }
    for(int i=0;i<N-1;i++)
    {
		ar[i]=FindLCP(L[i].p,L[i+1].p);
		//cout<<i<<" "<<ar[i]<<endl;
    }
    for(int i=0;i<N;i++)
    {
		if(L[i].p>y)update(i,1,tree3);
		else if(L[i].p>x&&L[i].p<y)update(i,1,tree2);
		else if(L[i].p<x)update(i,1,tree1);
		ma[i][0]=i;
    }

    for(int j=1;(1<<j)<=N;j++)
    {
        for(int i=0;(i+(1<<j))<=N-1;i++)
        {
            if(ar[ma[i][j-1]]<ar[ma[i+(1<<(j-1))][j-1]])
            {
                ma[i][j]=ma[i][j-1];
            }
            else ma[i][j]=ma[i+(1<<(j-1))][j-1];
        }
    }//cout<<"aman "<<N<<endl;
    bin(2,N-2);
    for(int i=l-1;i>=1;i--)
    {//cout<<ans[i]<<endl;
		ans[i]+=ans[i+1];
    }
    for(int i=1;i<=l;i++)
    {
		if(i!=1)cout<<" ";
		cout<<ans[i];
    }
    cout<<endl;

}
int main()
{
	int t=1,tmp,last;
	string a,b,c,s;
	//scanf("%d",&t);
	while(t--)
	{
		cin>>a>>b>>c;
		x=a.length();
		l=min(min(a.length(),b.length()),c.length());
		y=x+b.length()+1;
		s=a+"&"+b+"$"+c;
		N=s.length();
		for(int i=0;i<N;i++)P[0][i] = s[i];
		solve();
	}
}


#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<stack>

using namespace std;

#define sd(x) scanf("%d",&x);
#define LL long long
#define LD long double
#define PB push_back
#define MP make_pair
#define F first
#define S second
#define Fill(a, b) memset(a, b, sizeof(a))
#define INF 2000000009

typedef pair<int,int> PII;
typedef vector<int> VI;

#define MAXN 300010
#define MAXLG 22
#define INF 1000000009

int mod=1000000007;

int tree1[MAXN],tree2[MAXN],tree3[MAXN],x,y,ma[MAXN][MAXLG],l,last[MAXN],idx[MAXN];

LL ans[MAXN];

void update(int idx ,int val,int tree[])
{
	while (idx <= MAXN)
    {
		tree[idx] += val;
		idx += (idx & -idx);
	}
}
int read(int idx,int tree[])
{
	int sum = 0;
	while (idx > 0)
    {
		sum += tree[idx];
		idx -= (idx & -idx);
	}
	return sum;
}

struct entry
{
    int nr[2];
    int p;
} L[MAXN];

int P[MAXLG][MAXN];
int N,i;
int stp, cnt,ar[MAXN],comp[MAXN];

int cmp(entry a, entry b)
{
    if (a.nr[0]!=b.nr[0]) return a.nr[0]<b.nr[0];
    else return a.nr[1]<b.nr[1];
}

vector <entry > temp[MAXN];

void cnt_sort(int N)
{
	int curr=0;
	for(int i=0;i<N;i++)
	{
		if(L[i].nr[1]!=-1)temp[L[i].nr[1]].PB(L[i]);
		else {L[curr]=L[i];curr++;}
	}
	for(int i=0;i<max(N,32);i++)
	{
		int l=temp[i].size();
		for(int j=0;j<l;j++)
		{
			L[curr]=temp[i][j];curr++;

		}
		temp[i].clear();

	}
	//cout<<"amana "<<curr<<endl;
	curr=0;
	for(int i=0;i<N;i++)
	{
		if(L[i].nr[0]!=-1)temp[L[i].nr[0]].PB(L[i]);
		else {L[curr]=L[i];curr++;}
	}
	for(int i=0;i<max(N,32);i++)
	{
		int l=temp[i].size();
		for(int j=0;j<l;j++)
		{
			L[curr]=temp[i][j];curr++;
		}
		temp[i].clear();
	}//cout<<"aman "<<curr<<endl;
}

int FindLCP (int x,int y)
{
    int ans = 0 , k=0 , tmp=cnt;
    for (k=stp-1;k>= 0;k--,tmp>>=1)
    {
        if (x+tmp <= N && y+tmp <= N && P[k][x] == P[k][y])
        {// sort-index is same if the first k characters are same
            ans += tmp;
            // now we wish to find the characters that are same in the remaining strings
            x += tmp;
            y += tmp;
		}
	}
	return ans;
}

int rmq(int x,int y)
{
    int n=y-x+1,i=x,j=0,ans=x;
    while(n)
    {
        if(n&1)
        {
            if(ar[ans]>ar[ma[i][j]])ans=ma[i][j];
            i=i+(1<<j);
        }
        n>>=1;
        j++;

    }
    return ans;
}

void bin(int a,int b)
{
	if(a>=b)return;
	int mid=rmq(a,b);
	if(ar[mid]>l)return;
	LL x=read(b+1,tree1)-read(a-1,tree1);
	LL y=read(b+1,tree2)-read(a-1,tree2);
	LL z=read(b+1,tree3)-read(a-1,tree3);//cout<<a<<b<<mid<<x<<y<<z<<" "<<ar[mid]<<" "<<x*y*z<<endl;
	if(ar[mid]>last[a])
	{   //if(ar[mid]==3)cout<<a<<" "<<b<<mid<<x<<y<<z<<" "<<ar[mid]<<" "<<x*y*z<<endl;
		x=(x*y*z)%mod;
		ans[ar[mid]]+=x;
		ans[last[a]]-=x;
	}
	last[a]=ar[mid];
	last[mid+1]=ar[mid];
	bin(a,mid-1);
	bin(mid+1,b);
}

void solve()
{
    for(stp=1, cnt = 1; cnt < N; stp++, cnt *= 2)
    {
        for(i=0; i < N; i++)
        {
            L[i].nr[0]=P[stp- 1][i];
            L[i].nr[1]=i +cnt <N? P[stp -1][i+ cnt]:-1;
            L[i].p= i;
        }
        cnt_sort(N);
        //sort(L, L+N, cmp);
        for(i=0; i < N; i++)
            P[stp][L[i].p] =(((i> 0) && (L[i].nr[0]==L[i-1].nr[0]) && (L[i].nr[1] == L[i- 1].nr[1])) ? P[stp][L[i-1].p] : i);
    }
    //long long ans=N;
    //ans=(ans*(ans+1))/2;
    for(int i=0;i<N;i++)
    {
		if(i<=x)idx[i]=1;
		else if(i<=y)idx[i]=2;
		else idx[i]=3;
    }
    for(int i=0;i<N-1;i++)
    {
		ar[i]=FindLCP(L[i].p,L[i+1].p);
		//cout<<i<<" "<<ar[i]<<endl;
    }
    for(int i=0;i<N;i++)
    {
		if(L[i].p>y)update(i,1,tree3);
		else if(L[i].p>x&&L[i].p<y)update(i,1,tree2);
		else if(L[i].p<x)update(i,1,tree1);
		ma[i][0]=i;
    }

    for(int j=1;(1<<j)<=N;j++)
    {
        for(int i=0;(i+(1<<j))<=N-1;i++)
        {
            if(ar[ma[i][j-1]]<ar[ma[i+(1<<(j-1))][j-1]])
            {
                ma[i][j]=ma[i][j-1];
            }
            else ma[i][j]=ma[i+(1<<(j-1))][j-1];
        }
    }//cout<<"aman "<<N<<endl;
    bin(2,N-2);
    for(int i=l-1;i>=1;i--)
    {//cout<<ans[i]<<endl;
		ans[i]+=ans[i+1];
    }
    for(int i=1;i<=l;i++)
    {
		if(i!=1)cout<<" ";
		cout<<ans[i];
    }
    cout<<endl;

}
int main()
{
	int t=1,tmp,last;
	string a,b,c,s;
	//scanf("%d",&t);
	while(t--)
	{
		cin>>a>>b>>c;
		x=a.length();
		l=min(min(a.length(),b.length()),c.length());
		y=x+b.length()+1;
		s=a+"&"+b+"$"+c;
		N=s.length();
		for(int i=0;i<N;i++)P[0][i] = s[i];
		solve();
	}
}


#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<stack>

using namespace std;

#define sd(x) scanf("%d",&x);
#define LL long long
#define LD long double
#define PB push_back
#define MP make_pair
#define F first
#define S second
#define Fill(a, b) memset(a, b, sizeof(a))
#define INF 2000000009

typedef pair<int,int> PII;
typedef vector<int> VI;

#define MAXN 300010
#define MAXLG 22
#define INF 1000000009

int mod=1000000007;

int tree1[MAXN],tree2[MAXN],tree3[MAXN],x,y,ma[MAXN][MAXLG],l,last[MAXN],idx[MAXN];

LL ans[MAXN];

void update(int idx ,int val,int tree[])
{
	while (idx <= MAXN)
    {
		tree[idx] += val;
		idx += (idx & -idx);
	}
}
int read(int idx,int tree[])
{
	int sum = 0;
	while (idx > 0)
    {
		sum += tree[idx];
		idx -= (idx & -idx);
	}
	return sum;
}

struct entry
{
    int nr[2];
    int p;
} L[MAXN];

int P[MAXLG][MAXN];
int N,i;
int stp, cnt,ar[MAXN],comp[MAXN];

int cmp(entry a, entry b)
{
    if (a.nr[0]!=b.nr[0]) return a.nr[0]<b.nr[0];
    else return a.nr[1]<b.nr[1];
}

vector <entry > temp[MAXN];

void cnt_sort(int N)
{
	int curr=0;
	for(int i=0;i<N;i++)
	{
		if(L[i].nr[1]>-1)temp[L[i].nr[1]].PB(L[i]);
		else {L[curr]=L[i];curr++;}
	}
	for(int i=0;i<max(N,32);i++)
	{
		int l=temp[i].size();
		for(int j=0;j<l;j++)
		{
			L[curr]=temp[i][j];curr++;

		}
		temp[i].clear();

	}
	//cout<<"amana "<<curr<<endl;
	curr=0;
	for(int i=0;i<N;i++)
	{
		if(L[i].nr[0]>-1)temp[L[i].nr[0]].PB(L[i]);
		else {L[curr]=L[i];curr++;}
	}
	for(int i=0;i<max(N,32);i++)
	{
		int l=temp[i].size();
		for(int j=0;j<l;j++)
		{
			L[curr]=temp[i][j];curr++;
		}
		temp[i].clear();
	}//cout<<"aman "<<curr<<endl;
}

int FindLCP (int x,int y)
{
    int ans = 0 , k=0 , tmp=cnt;
    for (k=stp-1;k>= 0;k--,tmp>>=1)
    {
        if (x+tmp <= N && y+tmp <= N && P[k][x] == P[k][y])
        {// sort-index is same if the first k characters are same
            ans += tmp;
            // now we wish to find the characters that are same in the remaining strings
            x += tmp;
            y += tmp;
		}
	}
	return ans;
}

int rmq(int x,int y)
{
    int n=y-x+1,i=x,j=0,ans=x;
    while(n)
    {
        if(n&1)
        {
            if(ar[ans]>ar[ma[i][j]])ans=ma[i][j];
            i=i+(1<<j);
        }
        n>>=1;
        j++;

    }
    return ans;
}

void bin(int a,int b)
{
	if(a>=b)return;
	int mid=rmq(a,b);
	if(ar[mid]>l)return;
	LL x=read(b+1,tree1)-read(a-1,tree1);
	LL y=read(b+1,tree2)-read(a-1,tree2);
	LL z=read(b+1,tree3)-read(a-1,tree3);//cout<<a<<b<<mid<<x<<y<<z<<" "<<ar[mid]<<" "<<x*y*z<<endl;
	if(ar[mid]>last[a])
	{   //if(ar[mid]==3)cout<<a<<" "<<b<<mid<<x<<y<<z<<" "<<ar[mid]<<" "<<x*y*z<<endl;
		x=(x*y*z)%mod;
		ans[ar[mid]]+=x;
		ans[last[a]]-=x;
	}
	last[a]=ar[mid];
	last[mid+1]=ar[mid];
	bin(a,mid-1);
	bin(mid+1,b);
}

void solve()
{
    for(stp=1, cnt = 1; cnt < N; stp++, cnt *= 2)
    {
        for(i=0; i < N; i++)
        {
            L[i].nr[0]=P[stp- 1][i];
            L[i].nr[1]=i +cnt <N? P[stp -1][i+ cnt]:-1;
            L[i].p= i;
        }
        cnt_sort(N);
        //sort(L, L+N, cmp);
        for(i=0; i < N; i++)
            P[stp][L[i].p] =(((i> 0) && (L[i].nr[0]==L[i-1].nr[0]) && (L[i].nr[1] == L[i- 1].nr[1])) ? P[stp][L[i-1].p] : i);
    }
    //long long ans=N;
    //ans=(ans*(ans+1))/2;
    for(int i=0;i<N;i++)
    {
		if(i<=x)idx[i]=1;
		else if(i<=y)idx[i]=2;
		else idx[i]=3;
    }
    for(int i=0;i<N-1;i++)
    {
		ar[i]=FindLCP(L[i].p,L[i+1].p);
		//cout<<i<<" "<<ar[i]<<endl;
    }
    for(int i=0;i<N;i++)
    {
		if(L[i].p>y)update(i,1,tree3);
		else if(L[i].p>x&&L[i].p<y)update(i,1,tree2);
		else if(L[i].p<x)update(i,1,tree1);
		ma[i][0]=i;
    }

    for(int j=1;(1<<j)<=N;j++)
    {
        for(int i=0;(i+(1<<j))<=N-1;i++)
        {
            if(ar[ma[i][j-1]]<ar[ma[i+(1<<(j-1))][j-1]])
            {
                ma[i][j]=ma[i][j-1];
            }
            else ma[i][j]=ma[i+(1<<(j-1))][j-1];
        }
    }//cout<<"aman "<<N<<endl;
    bin(2,N-2);
    for(int i=l-1;i>=1;i--)
    {//cout<<ans[i]<<endl;
		ans[i]+=ans[i+1];
		ans[i]%=mod;
		ans[i]+=mod;
		ans[i]%=mod;
    }
    for(int i=1;i<=l;i++)
    {
		if(i!=1)cout<<" ";
		cout<<ans[i];
    }
    cout<<endl;

}
int main()
{
	int t=1,tmp,last;
	string a,b,c,s;
	//scanf("%d",&t);
	while(t--)
	{
		cin>>a>>b>>c;
		x=a.length();
		l=min(min(a.length(),b.length()),c.length());
		y=x+b.length()+1;
		s=a+"&"+b+"$"+c;
		N=s.length();
		for(int i=0;i<N;i++)P[0][i] = s[i]-97;
		solve();
	}
}


#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<stack>

using namespace std;

#define sd(x) scanf("%d",&x);
#define LL long long
#define LD long double
#define PB push_back
#define MP make_pair
#define F first
#define S second
#define Fill(a, b) memset(a, b, sizeof(a))
#define INF 2000000009

typedef pair<int,int> PII;
typedef vector<int> VI;

#define MAXN 300010
#define MAXLG 22
#define INF 1000000009

int mod=1000000007;

int tree1[MAXN],tree2[MAXN],tree3[MAXN],x,y,ma[MAXN][MAXLG],l,last[MAXN],idx[MAXN];

LL ans[MAXN];

void update(int idx ,int val,int tree[])
{
	while (idx <= MAXN)
    {
		tree[idx] += val;
		idx += (idx & -idx);
	}
}
int read(int idx,int tree[])
{
	int sum = 0;
	while (idx > 0)
    {
		sum += tree[idx];
		idx -= (idx & -idx);
	}
	return sum;
}

struct entry
{
    int nr[2];
    int p;
} L[MAXN];

int P[MAXLG][MAXN];
int N,i;
int stp, cnt,ar[MAXN],comp[MAXN];

int cmp(entry a, entry b)
{
    if (a.nr[0]!=b.nr[0]) return a.nr[0]<b.nr[0];
    else return a.nr[1]<b.nr[1];
}

int FindLCP (int x,int y)
{
    int ans = 0 , k=0 , tmp=cnt;
    for (k=stp-1;k>= 0;k--,tmp>>=1)
    {
        if (x+tmp <= N && y+tmp <= N && P[k][x] == P[k][y])
        {// sort-index is same if the first k characters are same
            ans += tmp;
            // now we wish to find the characters that are same in the remaining strings
            x += tmp;
            y += tmp;
		}
	}
	return ans;
}

int rmq(int x,int y)
{
    int n=y-x+1,i=x,j=0,ans=x;
    while(n)
    {
        if(n&1)
        {
            if(ar[ans]>ar[ma[i][j]])ans=ma[i][j];
            i=i+(1<<j);
        }
        n>>=1;
        j++;

    }
    return ans;
}

void bin(int a,int b)
{
	if(a>=b)return;
	int mid=rmq(a,b);
	if(ar[mid]>l)return;
	LL x=read(b+1,tree1)-read(a-1,tree1);
	LL y=read(b+1,tree2)-read(a-1,tree2);
	LL z=read(b+1,tree3)-read(a-1,tree3);//cout<<a<<b<<mid<<x<<y<<z<<" "<<ar[mid]<<" "<<x*y*z<<endl;
	if(ar[mid]>last[a])
	{   //if(ar[mid]==3)cout<<a<<" "<<b<<mid<<x<<y<<z<<" "<<ar[mid]<<" "<<x*y*z<<endl;
		x=(x*y*z)%mod;
		ans[ar[mid]]+=x;
		ans[last[a]]-=x;
	}
	last[a]=ar[mid];
	last[mid+1]=ar[mid];
	bin(a,mid-1);
	bin(mid+1,b);
}

void solve()
{
    for(stp=1, cnt = 1; cnt < N; stp++, cnt *= 2)
    {
        for(i=0; i < N; i++)
        {
            L[i].nr[0]=P[stp- 1][i];
            L[i].nr[1]=i +cnt <N? P[stp -1][i+ cnt]:-1;
            L[i].p= i;
        }
        sort(L, L+N, cmp);
        for(i=0; i < N; i++)
            P[stp][L[i].p] =(((i> 0) && (L[i].nr[0]==L[i-1].nr[0]) && (L[i].nr[1] == L[i- 1].nr[1])) ? P[stp][L[i-1].p] : i);
    }
    //long long ans=N;
    //ans=(ans*(ans+1))/2;
    for(int i=0;i<N;i++)
    {
		if(i<=x)idx[i]=1;
		else if(i<=y)idx[i]=2;
		else idx[i]=3;
    }
    for(int i=0;i<N-1;i++)
    {
		ar[i]=FindLCP(L[i].p,L[i+1].p);
		//cout<<i<<" "<<ar[i]<<endl;
    }
    for(int i=0;i<N;i++)
    {
		if(L[i].p>y)update(i,1,tree3);
		else if(L[i].p>x&&L[i].p<y)update(i,1,tree2);
		else if(L[i].p<x)update(i,1,tree1);
		ma[i][0]=i;
    }

    for(int j=1;(1<<j)<=N;j++)
    {
        for(int i=0;(i+(1<<j))<=N-1;i++)
        {
            if(ar[ma[i][j-1]]<ar[ma[i+(1<<(j-1))][j-1]])
            {
                ma[i][j]=ma[i][j-1];
            }
            else ma[i][j]=ma[i+(1<<(j-1))][j-1];
        }
    }//cout<<"aman "<<N<<endl;
    bin(2,N-2);
    for(int i=l-1;i>=1;i--)
    {//cout<<ans[i]<<endl;
		ans[i]+=ans[i+1];
    }
    for(int i=1;i<=l;i++)
    {
		if(i!=1)cout<<" ";
		cout<<ans[i];
    }
    cout<<endl;

}
int main()
{
	int t=1,tmp,last;
	string a,b,c,s;
	//scanf("%d",&t);
	while(t--)
	{
		cin>>a>>b>>c;
		x=a.length();
		l=min(min(a.length(),b.length()),c.length());
		y=x+b.length()+1;
		s=a+"&"+b+"$"+c;
		N=s.length();
		for(int i=0;i<N;i++)P[0][i] = s[i];
		solve();
	}
}


#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<stack>

using namespace std;

#define sd(x) scanf("%d",&x);
#define LL long long
#define LD long double
#define PB push_back
#define MP make_pair
#define F first
#define S second
#define Fill(a, b) memset(a, b, sizeof(a))
#define INF 2000000009

typedef pair<int,int> PII;
typedef vector<int> VI;

#define MAXN 300010
#define MAXLG 22
#define INF 1000000009

int mod=1000000007;

int tree1[MAXN],tree2[MAXN],tree3[MAXN],x,y,ma[MAXN][MAXLG],l,last[MAXN],idx[MAXN];

LL ans[MAXN];

void update(int idx ,int val,int tree[])
{
	while (idx <= MAXN)
    {
		tree[idx] += val;
		idx += (idx & -idx);
	}
}
int read(int idx,int tree[])
{
	int sum = 0;
	while (idx > 0)
    {
		sum += tree[idx];
		idx -= (idx & -idx);
	}
	return sum;
}

struct entry
{
    int nr[2];
    int p;
} L[MAXN];

int P[MAXLG][MAXN];
int N,i;
int stp, cnt,ar[MAXN],comp[MAXN];

int cmp(entry a, entry b)
{
    if (a.nr[0]!=b.nr[0]) return a.nr[0]<b.nr[0];
    else return a.nr[1]<b.nr[1];
}

vector <entry > temp[MAXN];

void cnt_sort(int N)
{
	int curr=0;
	for(int i=0;i<N;i++)
	{
		if(L[i].nr[1]>-1)temp[L[i].nr[1]].PB(L[i]);
		else {L[curr]=L[i];curr++;}
	}
	for(int i=0;i<max(N,32);i++)
	{
		int l=temp[i].size();
		for(int j=0;j<l;j++)
		{
			L[curr]=temp[i][j];curr++;

		}
		temp[i].clear();

	}
	//cout<<"amana "<<curr<<endl;
	curr=0;
	for(int i=0;i<N;i++)
	{
		if(L[i].nr[0]>-1)temp[L[i].nr[0]].PB(L[i]);
		else {L[curr]=L[i];curr++;}
	}
	for(int i=0;i<max(N,32);i++)
	{
		int l=temp[i].size();
		for(int j=0;j<l;j++)
		{
			L[curr]=temp[i][j];curr++;
		}
		temp[i].clear();
	}//cout<<"aman "<<curr<<endl;
}

int FindLCP (int x,int y)
{
    int ans = 0 , k=0 , tmp=cnt;
    for (k=stp-1;k>= 0;k--,tmp>>=1)
    {
        if (x+tmp <= N && y+tmp <= N && P[k][x] == P[k][y])
        {// sort-index is same if the first k characters are same
            ans += tmp;
            // now we wish to find the characters that are same in the remaining strings
            x += tmp;
            y += tmp;
		}
	}
	return ans;
}

int rmq(int x,int y)
{
    int n=y-x+1,i=x,j=0,ans=x;
    while(n)
    {
        if(n&1)
        {
            if(ar[ans]>ar[ma[i][j]])ans=ma[i][j];
            i=i+(1<<j);
        }
        n>>=1;
        j++;

    }
    return ans;
}

void bin(int a,int b)
{
	if(a>=b)return;
	int mid=rmq(a,b);
	if(ar[mid]>l)return;
	LL x=read(b+1,tree1)-read(a-1,tree1);
	LL y=read(b+1,tree2)-read(a-1,tree2);
	LL z=read(b+1,tree3)-read(a-1,tree3);//cout<<a<<b<<mid<<x<<y<<z<<" "<<ar[mid]<<" "<<x*y*z<<endl;
	if(ar[mid]>last[a])
	{   //if(ar[mid]==3)cout<<a<<" "<<b<<mid<<x<<y<<z<<" "<<ar[mid]<<" "<<x*y*z<<endl;
		x=(x*y*z)%mod;
		ans[ar[mid]]+=x;
		ans[last[a]]-=x;
	}
	last[a]=ar[mid];
	last[mid+1]=ar[mid];
	bin(a,mid-1);
	bin(mid+1,b);
}

void solve()
{
    for(stp=1, cnt = 1; cnt < N; stp++, cnt *= 2)
    {
        for(i=0; i < N; i++)
        {
            L[i].nr[0]=P[stp- 1][i];
            L[i].nr[1]=i +cnt <N? P[stp -1][i+ cnt]:-1;
            L[i].p= i;
        }
        cnt_sort(N);
        //sort(L, L+N, cmp);
        for(i=0; i < N; i++)
            P[stp][L[i].p] =(((i> 0) && (L[i].nr[0]==L[i-1].nr[0]) && (L[i].nr[1] == L[i- 1].nr[1])) ? P[stp][L[i-1].p] : i);
    }
    //long long ans=N;
    //ans=(ans*(ans+1))/2;
    for(int i=0;i<N;i++)
    {
		if(i<=x)idx[i]=1;
		else if(i<=y)idx[i]=2;
		else idx[i]=3;
    }
    for(int i=0;i<N-1;i++)
    {
		ar[i]=FindLCP(L[i].p,L[i+1].p);
		//cout<<i<<" "<<ar[i]<<endl;
    }
    for(int i=0;i<N;i++)
    {
		if(L[i].p>y)update(i,1,tree3);
		else if(L[i].p>x&&L[i].p<y)update(i,1,tree2);
		else if(L[i].p<x)update(i,1,tree1);
		ma[i][0]=i;
    }

    for(int j=1;(1<<j)<=N;j++)
    {
        for(int i=0;(i+(1<<j))<=N-1;i++)
        {
            if(ar[ma[i][j-1]]<ar[ma[i+(1<<(j-1))][j-1]])
            {
                ma[i][j]=ma[i][j-1];
            }
            else ma[i][j]=ma[i+(1<<(j-1))][j-1];
        }
    }//cout<<"aman "<<N<<endl;
    bin(2,N-2);
    for(int i=l-1;i>=1;i--)
    {//cout<<ans[i]<<endl;
		ans[i]+=ans[i+1];
    }
    for(int i=1;i<=l;i++)
    {
		if(i!=1)cout<<" ";
		cout<<ans[i];
    }
    cout<<endl;

}
int main()
{
	int t=1,tmp,last;
	string a,b,c,s;
	//scanf("%d",&t);
	while(t--)
	{
		cin>>a>>b>>c;
		x=a.length();
		l=min(min(a.length(),b.length()),c.length());
		y=x+b.length()+1;
		s=a+"&"+b+"$"+c;
		N=s.length();
		for(int i=0;i<N;i++)P[0][i] = s[i]-97;
		solve();
	}
}


#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<stack>

using namespace std;

#define sd(x) scanf("%d",&x);
#define LL long long
#define LD long double
#define PB push_back
#define MP make_pair
#define F first
#define S second
#define Fill(a, b) memset(a, b, sizeof(a))
#define INF 2000000009

typedef pair<int,int> PII;
typedef vector<int> VI;

#define MAXN 300010
#define MAXLG 22
#define INF 1000000009

int mod=1000000007;

int tree1[MAXN],tree2[MAXN],tree3[MAXN],x,y,ma[MAXN][MAXLG],l,last[MAXN],idx[MAXN];

LL ans[MAXN];

void update(int idx ,int val,int tree[])
{
	while (idx <= MAXN)
    {
		tree[idx] += val;
		idx += (idx & -idx);
	}
}
int read(int idx,int tree[])
{
	int sum = 0;
	while (idx > 0)
    {
		sum += tree[idx];
		idx -= (idx & -idx);
	}
	return sum;
}

struct entry
{
    int nr[2];
    int p;
} L[MAXN];

int P[MAXLG][MAXN];
int N,i;
int stp, cnt,ar[MAXN],comp[MAXN];

int cmp(entry a, entry b)
{
    if (a.nr[0]!=b.nr[0]) return a.nr[0]<b.nr[0];
    else return a.nr[1]<b.nr[1];
}

int FindLCP (int x,int y)
{
    int ans = 0 , k=0 , tmp=cnt;
    for (k=stp-1;k>= 0;k--,tmp>>=1)
    {
        if (x+tmp <= N && y+tmp <= N && P[k][x] == P[k][y])
        {// sort-index is same if the first k characters are same
            ans += tmp;
            // now we wish to find the characters that are same in the remaining strings
            x += tmp;
            y += tmp;
		}
	}
	return ans;
}

int rmq(int x,int y)
{
    int n=y-x+1,i=x,j=0,ans=x;
    while(n)
    {
        if(n&1)
        {
            if(ar[ans]>ar[ma[i][j]])ans=ma[i][j];
            i=i+(1<<j);
        }
        n>>=1;
        j++;

    }
    return ans;
}

void bin(int a,int b)
{
	if(a>=b)return;
	int mid=rmq(a,b);
	LL x=read(b+1,tree1)-read(a-1,tree1);
	LL y=read(b+1,tree2)-read(a-1,tree2);
	LL z=read(b+1,tree3)-read(a-1,tree3);//cout<<a<<b<<mid<<x<<y<<z<<" "<<ar[mid]<<" "<<x*y*z<<endl;
	if(ar[mid]>last[a])
	{   //if(ar[mid]==3)cout<<a<<" "<<b<<mid<<x<<y<<z<<" "<<ar[mid]<<" "<<x*y*z<<endl;
		x=(x*y*z)%mod;
		ans[ar[mid]]+=x;
		ans[last[a]]-=x;
	}
	last[a]=ar[mid];
	last[mid+1]=ar[mid];
	bin(a,mid-1);
	bin(mid+1,b);
}

void solve()
{
    for(stp=1, cnt = 1; cnt < N; stp++, cnt *= 2)
    {
        for(i=0; i < N; i++)
        {
            L[i].nr[0]=P[stp- 1][i];
            L[i].nr[1]=i +cnt <N? P[stp -1][i+ cnt]:-1;
            L[i].p= i;
        }
        sort(L, L+N, cmp);
        for(i=0; i < N; i++)
            P[stp][L[i].p] =(((i> 0) && (L[i].nr[0]==L[i-1].nr[0]) && (L[i].nr[1] == L[i- 1].nr[1])) ? P[stp][L[i-1].p] : i);
    }
    //long long ans=N;
    //ans=(ans*(ans+1))/2;
    for(int i=0;i<N;i++)
    {
		if(i<=x)idx[i]=1;
		else if(i<=y)idx[i]=2;
		else idx[i]=3;
    }
    for(int i=0;i<N-1;i++)
    {
		ar[i]=FindLCP(L[i].p,L[i+1].p);
		//cout<<i<<" "<<ar[i]<<endl;
    }
    for(int i=0;i<N;i++)
    {
		if(L[i].p>y)update(i,1,tree3);
		else if(L[i].p>x&&L[i].p<y)update(i,1,tree2);
		else if(L[i].p<x)update(i,1,tree1);
		ma[i][0]=i;
    }

    for(int j=1;(1<<j)<=N-1;j++)
    {
        for(int i=0;(i+(1<<j))<=N-1;i++)
        {
            if(ar[ma[i][j-1]]<ar[ma[i+(1<<(j-1))][j-1]])
            {
                ma[i][j]=ma[i][j-1];
            }
            else ma[i][j]=ma[i+(1<<(j-1))][j-1];
        }
    }//cout<<"aman "<<N<<endl;
    bin(2,N-2);
    for(int i=l-1;i>=1;i--)
    {//cout<<ans[i]<<endl;
		ans[i]+=ans[i+1];
    }
    for(int i=1;i<=l;i++)
    {
		if(i!=1)cout<<" ";
		cout<<ans[i];
    }
    cout<<endl;

}
int main()
{
	int t=1,tmp,last;
	string a,b,c,s;
	//scanf("%d",&t);
	while(t--)
	{
		cin>>a>>b>>c;
		x=a.length();
		l=min(min(a.length(),b.length()),c.length());
		y=x+b.length()+1;
		s=a+"&"+b+"$"+c;
		N=s.length();
		for(int i=0;i<N;i++)P[0][i] = s[i];
		solve();
	}
}


#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

#define n   600005
#define P   1000000007
#define For(i,a,b)  for(int i=a;i<=b;i++)

char    s[n];
int     N,Ans[n],Max[n];

bool    Cmp(int a,int b)    {return Max[a]>Max[b];}

struct  SAM{
        int     L,D,F[n],Ord[n],siz[n][4],A[n][27];
        SAM()   {L=D=1;}

        void    Add(int x,int bel){
            int np=++D,p=L,q,nq;    Max[np]=Max[p]+1;
            for (;p&&!A[p][x];p=F[p])   A[p][x]=np;
            if  (!p)    F[np]=1;    else
            if  (Max[q=A[p][x]]==Max[p]+1)  F[np]=q;
            else    {
                F[nq=++D]=F[q]; Max[nq]=Max[p]+1;
                For(i,0,26) A[nq][i]=A[q][i];
                for (F[q]=F[np]=nq;p&&A[p][x]==q;p=F[p])    A[p][x]=nq;
            }   L=np;   siz[np][bel]++;
        }

        void    Work(){
            For(i,1,D)  Ord[i]=i;
            sort(Ord+1,Ord+D+1,Cmp);
            For(i,1,D)  {
                int x=Ord[i],y=F[x],k=1;
                For(j,0,2)  siz[y][j]+=siz[x][j],k=1ll*k*siz[x][j]%P;
                (Ans[Max[x]]+=k)%=P;    (Ans[Max[y]]-=k)%=P;
            }
            for (int i=D;i;i--) (Ans[i]+=Ans[i+1])%=P;
        }
}S;

int     main(){
        N=1<<30;
        For(i,0,2)  {
            scanf("%s",s+1);int Len=strlen(s+1);N=min(N,Len);
            For(j,1,Len)    S.Add(s[j]-'a',i);  S.Add(26,3);
        }   S.Work();
        For(i,1,N)  printf("%d ",(Ans[i]+P)%P);
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef long long LL;

struct Sam
{
    int l, fa, son[29];
    int r[3];
};
const int Mo = 1000000007;
const int maxlong = int(1e9);
const int N = int(3e5)+5;
char s[N];
Sam S[N<<1];
int tot , last , n , len;
int du[N<<1];
bool v[N<<1];
LL Ans[N];

void add(int x,int b)
{
    int p = ++tot , bj = last;
    S[p].l = S[bj].l + 1;
    for(; bj!=-1 && !S[bj].son[x]; bj=S[bj].fa) S[bj].son[x] = p;
    if (bj == -1) S[p].fa = 0;else
    if (S[bj].l+1 == S[S[bj].son[x]].l) S[p].fa = S[bj].son[x];else
    {
        int r = ++tot , q = S[bj].son[x];
        S[r] = S[q];
        fo(k,0,2) S[r].r[k] = 0;
        S[p].fa = S[q].fa = r;
        S[r].l = S[bj].l+1;
        for(; bj!=-1 && S[bj].son[x]==q; bj=S[bj].fa) S[bj].son[x] = r;
    }
    S[last = p].r[b] ++;
}

void Init()
{
    n = maxlong;
    S[0].fa = -1;
    tot = last = 0;
    fo(j,0,2)
    {
        scanf("%s",s+1);
        len = strlen(s+1);
        n = min(n , len);
        fo(i,1,len) add(s[i] - 'a' , j);
        add('z'-'a'+j+1 , j);
    }
}

void Dfs(int x)
{
    if (!v[x]) return;
    v[x] = 0;
    if (S[x].fa > 0)
    {
        fo(k,0,2) (S[S[x].fa].r[k] += S[x].r[k]) %= Mo;
        du[S[x].fa] --;
        if (!du[S[x].fa]) Dfs(S[x].fa);
    }
}

void Work()
{
    fo(i,1,tot) du[S[i].fa] ++ , v[i] = 1;
    fo(i,1,tot)
        if (!du[i]) Dfs(i);
    fo(i,1,tot)
    {
        int tmp = LL(S[i].r[0]) * S[i].r[1] % Mo * S[i].r[2] % Mo;
        (Ans[S[i].l] += tmp) %= Mo;
        (Ans[S[S[i].fa].l] -= tmp) %= Mo;
    }
    fd(i,n,1) Ans[i] = ((Ans[i] + Ans[i+1]) % Mo + Mo) % Mo;
    fo(i,1,n) printf("%d ",Ans[i]);
}

int main()
{

    Init();
    Work();

    return 0;
}


#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

#define M 300010
#define LL long long
#define L_L "%I64d"
using namespace std;
char a[M], b[M], c[M], ch[M];
int n, la, lb, lc;
int w[M], rank[M], nank[M], h[M], sa[M], top[M], next[M], fa[M], s[M][5];
LL ans[M], mo = 1e9 + 7;

void init() {
	scanf ("%s%s%s", a + 1, b + 1, c + 1);
	la = strlen (a + 1), lb = strlen (b + 1), lc = strlen (c + 1);
	n = la + lb + lc + 2;
	for (int i = 1; i <= la; i++) ch[i] = a[i];
	ch[la + 1] = '*';
	for (int i = 1; i <= lb; i++) ch[la + 1 + i] = b[i];
	ch[la + lb + 2] = '#';
	for (int i = 1; i <= lc; i++) ch[la + lb + 2 + i] = c[i];
}

bool cmpch (int i, int j) {return ch[i] < ch[j];}

void prep() {
	for (int i = 1; i <= n; i++) w[i] = i;
	for (int L = 1, l; l = (L >> 1), l <= n; L <<= 1) {
		if (l == 0) {
			sort (w + 1, w + 1 + n, cmpch);
			for (int j = 1, u, v; j <= n; j++) {
				u = w[j], v = w[j - 1];
				if (j > 1 && ch[u] == ch[v])
					rank[u] = rank[v];
				else
					rank[u] = rank[v] + 1;
			}
		}
		else {
			for (int j = 1, t; j <= n; j++)
				t = min (j + l, n + 1),	next[j] = top[ rank[t] ], top[ rank[t] ] = j;

			w[0] = 0;
			for (int j = 0; j <= n; j++)
				for (; top[j]; top[j] = next[ top[j] ])
					w[ ++ w[0] ] = top[j];

			for (int j = n; j >= 1; j--)
				next[ w[j] ] = top[ rank[ w[j] ] ], top[ rank[ w[j] ] ] = w[j];

			w[0] = 0;
			for (int j = 1; j <= n; j++)
				for (; top[j]; top[j] = next[ top[j] ])
					w[ ++ w[0] ] = top[j];

			memset (nank, 0, sizeof (nank));
			for (int j = 1, u, v; j <= n; j++) {
				u = w[j], v = w[j - 1];
				if (j > 1 && rank[u] == rank[v] && rank[min (u + l, n + 1)] == rank[min (v + l, n + 1)])
					nank[u] = nank[v];
				else
					nank[u] = nank[v] + 1;
			}
			for (int j = 1; j <= n; j++)
				rank[j] = nank[j];
		}
	}
	for (int i = 1; i <= n; i++) sa[ rank[i] ] = i;
	for (int i = 1, j; i <= n; i++) {
		for (j = max (h[rank[i - 1]] - 1, 0); rank[i] - 1 && ch[sa[rank[i] - 1] + j] == ch[i + j]; j++);
		h[rank[i]] = j;
	}
}

bool cmph (int i, int j) {return h[i] > h[j];}

int gtf (int o) {return fa[o] == o? o : fa[o] = gtf (fa[o]);}

void link (int x, int y, int k) {
	int fx = gtf (x), fy = gtf (y);
	ans[k] -= 1LL * s[fx][1] * s[fx][2] * s[fx][3];
	ans[k] -= 1LL * s[fy][1] * s[fy][2] * s[fy][3];
	for (int i = 1; i <= 3; i++) s[fx][i] += s[fy][i];
	fa[fy] = fx;
	ans[k] = (ans[k] + 1LL * s[fx][1] * s[fx][2] * s[fx][3]) % mo;
}

void work() {
	for (int i = 1; i <= n; i++) {
		w[i] = i, fa[i] = i;
		if (i > la + lb + 2) s[ rank[i] ][3] = 1;
		else if (i > la + 1 && i < la + lb + 2) s[ rank[i] ][2] = 1;
		else if (i < la + 1) s[ rank[i] ][1] = 1;
	}
	sort (w + 1, w + 1 + n, cmph);
	for (int i = 1; i <= n; i++) {
		if (w[i] > 1)
			link (w[i] - 1, w[i], h[ w[i] ]);
	}
	int l = min (min (la, lb), lc);
	for (int i = l; i >= 1; i--) ans[i] = (ans[i] + ans[i + 1]) % mo;
	for (int i = 1; i <= l; i++) printf (L_L"\n", ans[i]);
}

int main()
{
	init();
	prep();
	work();
	return 0;
}


#include <bits/stdc++.h>
#define in freopen("solve_in.txt", "r", stdin);
#define bug(x) printf("Line #%d: >>>>><<<\n", (x));
typedef long long LL;

using namespace std;
const int M = 1000000007;

const int maxn = 3*(int)1e5+1000;
int s[maxn], sa[maxn], t[maxn], t2[maxn], c[maxn], h[maxn], rk[maxn];
int n;
char str[3][maxn];
LL cnt[3][maxn];
int fa[maxn];
int slen[3];
int res[maxn];

vector<int> g[maxn];

void buildSa(int m)
{
    int *x = t, *y = t2;
    for(int i = 0; i < m; i++) c[i] = 0;
    for(int i = 0; i < n; i++) c[x[i] = s[i]]++;
    for(int i = 1; i < m; i++) c[i] += c[i-1];
    for(int i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;

    for(int k = 1; k <= n; k <<= 1)
    {
        int p = 0;
        for(int i = n-k; i < n; i++) y[p++] = i;

        for(int i = 0; i < m; i++) c[i] = 0;
        for(int i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i]-k;
        for(int i = 0; i < n; i++) c[x[y[i]]]++;
        for(int i = 1; i < m; i++) c[i] += c[i-1];

        for(int  i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
        swap(x, y);
        p = 1;
        x[sa[0]] = 0;
        for(int i = 1; i < n; i++)
            x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k] ? p-1 : p++;
        if(p >= n) break;
        m = p;
    }
}
void getHeight()
{
    int j, k = 0;
    h[0] = 0;
    for(int i = 0; i < n; i++) rk[sa[i]] = i;
    for(int i = 0; i < n; i++)
    {

        if(k) k--;
        if(rk[i] == 0)
            continue;
        j = sa[rk[i]-1];
        while(s[i+k] == s[j+k]) k++;
        h[rk[i]] = k;
    }
}
int findset(int x)
{
    return x == fa[x] ? x : fa[x] = findset(fa[x]);
}
void Union(int x, int y)
{
    int fx = findset(x);
    int fy = findset(y);
    if(fx == fy)
        return;
    for(int i = 0; i < 3; i++)
        cnt[i][fx] += cnt[i][fy];
    fa[fy] = fx;
}

void init()
{
    for(int i = 0; i < maxn; i++)
    {
        fa[i] = i;
    }
    int base = 0;
    for(int k = 0; k < 3; k++)
    {
        for(int j = 0; j < slen[k]; j++)
            cnt[k][j+base+k] = 1;
        base += slen[k];
    }
}

void solve()
{
    LL ans = 0;
    for(int i = n-1; i > 0; i--)
    {
        int sz = g[i].size();
        for(int j = 0; j < sz; j++)
        {
            int v = g[i][j];
            int x = findset(sa[v-1]);
            int y = findset(sa[v]);
            ans -= cnt[0][x]*cnt[1][x]%M*cnt[2][x]%M;
            if(ans < 0)
                ans += M;
            ans -= cnt[0][y]*cnt[1][y]%M*cnt[2][y]%M;
            if(ans < 0)
                ans += M;
            Union(x, y);
            x = findset(x);
            ans += cnt[0][x]*cnt[1][x]%M*cnt[2][x]%M;
        }

        res[i] = ans;
    }

    int len = min(slen[0], min(slen[1], slen[2]));
    for(int i = 1; i <= len; i++)
        printf("%d%c", res[i], i == len ? '\n' : ' ');
}
int main()
{

    scanf("%s%s%s", str[0], str[1], str[2]);
    for(int k = 0; k < 3; k++)
    {
        for(int i = 0; str[k][i]; i++)
        {
            s[n++] = str[k][i] - 'a' + 1;
            slen[k]++;
        }
        s[n++] = 30+k;
    }
    s[n++] = 0;
    init();
    buildSa(60);
    getHeight();
    for(int i = 1; i < n; i++)
        if(h[i])
            g[h[i]].push_back(i);
    solve();
    return 0;
}


#include <bits/stdc++.h>
#define in freopen("solve_in.txt", "r", stdin);
#define bug(x) printf("Line #%d: >>>>><<<\n", (x));
typedef long long LL;

using namespace std;
const LL M = 1000000007;

const int maxn = 3*(int)1e5+1000;
int s[maxn], sa[maxn], t[maxn], t2[maxn], c[maxn], h[maxn], rk[maxn];
int n;
char str[3][maxn];
LL cnt[3][maxn];
int fa[maxn];
int slen[3];
int res[maxn];

vector<int> g[maxn];

void buildSa(int m)
{
    int *x = t, *y = t2;
    for(int i = 0; i < m; i++) c[i] = 0;
    for(int i = 0; i < n; i++) c[x[i] = s[i]]++;
    for(int i = 1; i < m; i++) c[i] += c[i-1];
    for(int i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;

    for(int k = 1; k <= n; k <<= 1)
    {
        int p = 0;
        for(int i = n-k; i < n; i++) y[p++] = i;

        for(int i = 0; i < m; i++) c[i] = 0;
        for(int i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i]-k;
        for(int i = 0; i < n; i++) c[x[y[i]]]++;
        for(int i = 1; i < m; i++) c[i] += c[i-1];

        for(int  i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
        swap(x, y);
        p = 1;
        x[sa[0]] = 0;
        for(int i = 1; i < n; i++)
            x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k] ? p-1 : p++;
        if(p >= n) break;
        m = p;
    }
}
void getHeight()
{
    int j, k = 0;
    h[0] = 0;
    for(int i = 0; i < n; i++) rk[sa[i]] = i;
    for(int i = 0; i < n; i++)
    {

        if(k) k--;
        if(rk[i] == 0)
            continue;
        j = sa[rk[i]-1];
        while(s[i+k] == s[j+k]) k++;
        h[rk[i]] = k;
    }
}
int findset(int x)
{
    return x == fa[x] ? x : fa[x] = findset(fa[x]);
}
void Union(int x, int y)
{
    int fx = findset(x);
    int fy = findset(y);
    if(fx == fy)
        return;
    for(int i = 0; i < 3; i++)
        cnt[i][fx] += cnt[i][fy];
    fa[fy] = fx;
}

void init()
{
    for(int i = 0; i < maxn; i++)
    {
        fa[i] = i;
    }
    int base = 0;
    for(int k = 0; k < 3; k++)
    {
        for(int j = 0; j < slen[k]; j++)
            cnt[k][j+base+k] = 1;
        base += slen[k];
    }
}

void solve()
{
    LL ans = 0;
    for(int i = n-1; i > 0; i--)
    {
        int sz = g[i].size();
        for(int j = 0; j < sz; j++)
        {
            int v = g[i][j];
            int x = findset(sa[v-1]);
            int y = findset(sa[v]);
            ans -= cnt[0][x]*cnt[1][x]%M*cnt[2][x]%M;
            if(ans < 0)
                ans += M;
            ans -= cnt[0][y]*cnt[1][y]%M*cnt[2][y]%M;
            if(ans < 0)
                ans += M;
            Union(x, y);
            x = findset(x);
            ans = (ans+cnt[0][x]*cnt[1][x]%M*cnt[2][x]%M)%M;

        }

        res[i] = ans;
    }

    int len = min(slen[0], min(slen[1], slen[2]));
    for(int i = 1; i <= len; i++)
        printf("%d%c", res[i], i == len ? '\n' : ' ');
}
int main()
{

    scanf("%s%s%s", str[0], str[1], str[2]);
    for(int k = 0; k < 3; k++)
    {
        for(int i = 0; str[k][i]; i++)
        {
            s[n++] = str[k][i] - 'a' + 1;
            slen[k]++;
        }
        s[n++] = 30+k;
    }
    s[n++] = 0;
    init();
    buildSa(60);
    getHeight();
    for(int i = 1; i < n; i++)
        if(h[i])
            g[h[i]].push_back(i);
    solve();
    return 0;
}


#include <bits/stdc++.h>
#define in freopen("solve_in.txt", "r", stdin);
#define bug(x) printf("Line #%d: >>>>><<<\n", (x));
typedef long long LL;

using namespace std;
const int M = 1000000007;

const int maxn = 3*(int)1e5+100;
int s[maxn], sa[maxn], t[maxn], t2[maxn], c[maxn], h[maxn], rk[maxn];
int n;
char str[3][maxn];
int cnt[3][maxn];
int fa[maxn];
int slen[3];
int res[maxn];

vector<int> g[maxn];

void buildSa(int m)
{
    int *x = t, *y = t2;
    for(int i = 0; i < m; i++) c[i] = 0;
    for(int i = 0; i < n; i++) c[x[i] = s[i]]++;
    for(int i = 1; i < m; i++) c[i] += c[i-1];
    for(int i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;

    for(int k = 1; k <= n; k <<= 1)
    {
        int p = 0;
        for(int i = n-k; i < n; i++) y[p++] = i;

        for(int i = 0; i < m; i++) c[i] = 0;
        for(int i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i]-k;
        for(int i = 0; i < n; i++) c[x[y[i]]]++;
        for(int i = 1; i < m; i++) c[i] += c[i-1];

        for(int  i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
        swap(x, y);
        p = 1;
        x[sa[0]] = 0;
        for(int i = 1; i < n; i++)
            x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k] ? p-1 : p++;
        if(p >= n) break;
        m = p;
    }
}
void getHeight()
{
    int j, k = 0;
    h[0] = 0;
    for(int i = 0; i < n; i++) rk[sa[i]] = i;
    for(int i = 0; i < n; i++)
    {

        if(k) k--;
        if(rk[i] == 0)
            continue;
        j = sa[rk[i]-1];
        while(s[i+k] == s[j+k]) k++;
        h[rk[i]] = k;
    }
}
int findset(int x)
{
    return x == fa[x] ? x : fa[x] = findset(fa[x]);
}
void Union(int x, int y)
{
    int fx = findset(x);
    int fy = findset(y);
    if(fx == fy)
        return;
    for(int i = 0; i < 3; i++)
        cnt[i][fx] += cnt[i][fy];
    fa[fy] = fx;
}

void init()
{
    for(int i = 0; i < maxn; i++)
    {
        fa[i] = i;
    }
    int base = 0;
    for(int k = 0; k < 3; k++)
    {
        for(int j = 0; j < slen[k]; j++)
            cnt[k][j+base+k] = 1;
        base += slen[k];
    }
}

void solve()
{
    int ans = 0;
    for(int i = n-1; i > 0; i--)
    {
        int sz = g[i].size();
//        if(sz) cout<<i<<' ';
        for(int j = 0; j < sz; j++)
        {
            int v = g[i][j];
            int x = findset(sa[v-1]);
            int y = findset(sa[v]);
//            cout<<sa[v-1]<<' '<<sa[v]<<endl;
            ans -= cnt[0][x]*cnt[1][x]%M*cnt[2][x]%M;
            if(ans < 0)
                ans += M;
            ans -= cnt[0][y]*cnt[1][y]%M*cnt[2][y]%M;
            if(ans < 0)
                ans += M;
            Union(x, y);
            x = findset(x);
            ans += cnt[0][x]*cnt[1][x]%M*cnt[2][x]%M;
        }
//        if(i == 2)
//        {
//            for(int k = 0; k < 3; k++){
//                cout<<cnt[k][8]<<' ';
//            }
//            cout<<endl;
//        }
        res[i] = ans;
    }

    int len = min(slen[0], min(slen[1], slen[2]));
    for(int i = 1; i <= len; i++)
        printf("%d%c", res[i], i == len ? '\n' : ' ');
}
int main()
{

    scanf("%s%s%s", str[0], str[1], str[2]);
    for(int k = 0; k < 3; k++)
    {
        for(int i = 0; str[k][i]; i++)
        {
            s[n++] = str[k][i] - 'a' + 1;
            slen[k]++;
        }
        s[n++] = 30+k;
    }
    s[n++] = 0;
     init();
    buildSa(60);
    getHeight();
    for(int i = 1; i < n; i++)
        if(h[i])
        {

            g[h[i]].push_back(i);
        }
    solve();
    return 0;
}


#include <stdio.h>
#include <string.h>

#define INF 1000000000
#define ll long long
#define MOD 1000000007
#define min(a, b) ((a) < (b) ? (a) : (b))

struct sNode {
    int l, r;
    int pl, pr;
    int pos;
};

sNode nodes[700000];
int nodesCnt;

char arr[300005];
int suffArr[300005];
int lcp[300005];
int size;
int tree;

int BuildTree(int l, int r)
{
    int cur = nodesCnt++;
    nodes[cur].l = l;
    nodes[cur].r = r;
    nodes[cur].pos = l;
    if (l < r) {
        nodes[cur].pl = BuildTree(l, (l+r)/2);
        nodes[cur].pr = BuildTree((l+r)/2+1, r);
    }
    return cur;
}

void Update(int i, int root)
{
    if (nodes[root].l < nodes[root].r) {
        if (i <= nodes[nodes[root].pl].r)
            Update(i, nodes[root].pl);
        else
            Update(i, nodes[root].pr);
        if (lcp[ nodes[nodes[root].pl].pos ] <= lcp[ nodes[nodes[root].pr].pos ])
            nodes[root].pos = nodes[nodes[root].pl].pos;
        else
            nodes[root].pos = nodes[nodes[root].pr].pos;
    }
}

int Get(int l, int r, int root)
{
    if (l <= nodes[root].l && r >= nodes[root].r)
        return nodes[root].pos;
    int ans = INF;
    int pos = -1;
    if (l <= nodes[nodes[root].pl].r && nodes[nodes[root].pl].l <= r) {
        int tmp = Get(l, r, nodes[root].pl);
        if (lcp[tmp] < ans) {
            ans = lcp[tmp];
            pos = tmp;
        }
    }
    if (l <= nodes[nodes[root].pr].r && nodes[nodes[root].pr].l <= r) {
        int tmp = Get(l, r, nodes[root].pr);
        if (lcp[tmp] < ans) {
            ans = lcp[tmp];
            pos = tmp;
        }
    }
    return pos;
}

char S1[300005];
char S2[300005];
char S3[300005];

int posInSuffArr[300005];
bool isBorder[300005];
int newSuffArr[300005];
int bucket[300005];
int nextFreePos[300005];

void BuildSuffArr()
{
    tree = BuildTree(0, size-1);
    int cnt[29]; memset(cnt, 0, sizeof(int)*29);
    for (int i = 0; i < size; i++) {
        cnt[arr[i]-('a'-3)]++;
        lcp[i] = INF;
    }
    for (int i = 0; i < 29; i++) {
        if (i) cnt[i] += cnt[i-1];
        lcp[cnt[i]] = 0;
        Update(cnt[i], tree);
        isBorder[cnt[i]] = true;
    }
    for (int i = 0; i < size; i++) {
        suffArr[ --cnt[arr[i]-('a'-3)] ] = i;
    }

    newSuffArr[0] = suffArr[0];
    posInSuffArr[suffArr[0]] = 0;
    for (int step = 1; step < size; step *= 2) {

        for (int i = 1; i < size; i++) {
            posInSuffArr[suffArr[i]] = i;
            if (isBorder[i])
                bucket[i] = i, nextFreePos[i] = i;
            else
                bucket[i] = bucket[i-1];
        }

        for (int i = 0; i < size; i++) {
            if (suffArr[i] >= step)
                newSuffArr[ nextFreePos[ bucket[ posInSuffArr[suffArr[i]-step] ] ]++ ] = suffArr[i]-step;
        }
        for (int i = 1; i < size; i++) {
            if (!isBorder[i] && bucket[posInSuffArr[newSuffArr[i]+step]] != bucket[posInSuffArr[newSuffArr[i-1]+step]]) {
                int a = bucket[posInSuffArr[newSuffArr[i]+step]];
                int b = bucket[posInSuffArr[newSuffArr[i-1]+step]];
                if (a > b) {
                    int tmp = a; a = b; b = tmp;
                }
                lcp[i] = step + lcp[ Get(a+1, b, tree) ];
            }
        }
        for (int i = 0; i < size; i++) {
            if (!isBorder[i] && lcp[i] != INF) isBorder[i] = true, Update(i, tree);
            suffArr[i] = newSuffArr[i];
        }
    }
}
ll ans[100005];
ll a[300005];
ll b[300005];
ll c[300005];

void Solve(int l, int r, int cur)
{
    if (l >= r) return;
    ll tmp = (a[r]-a[l-1])*(b[r]-b[l-1])*(c[r]-c[l-1]);
    tmp %= MOD;

    int i = Get(l+1, r, tree);

    ans[cur] = (ans[cur] + tmp)% MOD;
    ans[ lcp[i]+1 ] = (ans[ lcp[i]+1 ] + MOD - tmp)% MOD;

    Solve(l, i-1, lcp[i]+1);
    Solve(i, r, lcp[i]+1);
}

int main()
{
    /*
    scanf("%s", arr);
    size = strlen(arr);
    arr[size++] = 'a'-3;
    BuildSuffArr();
    for (int i = 0; i < size; i++) {
        printf("%d ", suffArr[i]);
    } printf("\n ");
    for (int i = 1; i < size; i++) {
        printf("%d ", lcp[i]);
    }
    return 0;
    */

    scanf("%s\n%s\n%s", S1, S2, S3);
    int N1 = strlen(S1);
    int N2 = strlen(S2);
    int N3 = strlen(S3);

    memcpy(arr, S1, N1);
    memcpy(arr+N1+1, S2, N2);
    memcpy(arr+N1+N2+2, S3, N3);
    arr[N1] = 'a'-1;
    arr[N1+N2+1] = 'a'-2;
    arr[N1+N2+N3+2] = 'a'-3;
    size = N1+N2+N3+3;
    BuildSuffArr();

    /*
    for (int i = 0; i < size; i++) printf("%d ", suffArr[i]);
    printf("\n ");
    for (int i = 1; i < size; i++) printf("%d ", lcp[i]);
    */

    for (int i = 3; i < size; i++) {
        a[i] = a[i-1];
        b[i] = b[i-1];
        c[i] = c[i-1];
        if (suffArr[i] < N1)
            a[i]++;
        else if (suffArr[i] < N1+N2+1)
            b[i]++;
        else
            c[i]++;
    }

    Solve(3, size-1, 1);

    int m = N1;
    if (N2 < m) m = N2;
    if (N3 < m) m = N3;
    for (int i = 1; i <= m; i++) {
        ans[i] = (ans[i] + ans[i-1] + MOD) % MOD;
        printf("%I64d ", ans[i]);
    }
}


#include <stdio.h>
#include <string.h>

#define INF 1000000000
#define ll long long
#define MOD 1000000007LL
#define min(a, b) ((a) < (b) ? (a) : (b))

struct sNode {
    int l, r;
    int pl, pr;
    int pos;
};

sNode nodes[700000];
int nodesCnt;

char arr[300005];
int suffArr[300005];
int lcp[300005];
int size;
int tree;

int BuildTree(int l, int r)
{
    int cur = nodesCnt++;
    nodes[cur].l = l;
    nodes[cur].r = r;
    nodes[cur].pos = l;
    if (l < r) {
        nodes[cur].pl = BuildTree(l, (l+r)/2);
        nodes[cur].pr = BuildTree((l+r)/2+1, r);
    }
    return cur;
}

void Update(int i, int root)
{
    if (nodes[root].l < nodes[root].r) {
        if (i <= nodes[nodes[root].pl].r)
            Update(i, nodes[root].pl);
        else
            Update(i, nodes[root].pr);
        if (lcp[ nodes[nodes[root].pl].pos ] <= lcp[ nodes[nodes[root].pr].pos ])
            nodes[root].pos = nodes[nodes[root].pl].pos;
        else
            nodes[root].pos = nodes[nodes[root].pr].pos;
    }
}

int Get(int l, int r, int root)
{
    if (l <= nodes[root].l && r >= nodes[root].r)
        return nodes[root].pos;
    int ans = INF;
    int pos = -1;
    if (l <= nodes[nodes[root].pl].r && nodes[nodes[root].pl].l <= r) {
        int tmp = Get(l, r, nodes[root].pl);
        if (lcp[tmp] < ans) {
            ans = lcp[tmp];
            pos = tmp;
        }
    }
    if (l <= nodes[nodes[root].pr].r && nodes[nodes[root].pr].l <= r) {
        int tmp = Get(l, r, nodes[root].pr);
        if (lcp[tmp] < ans) {
            ans = lcp[tmp];
            pos = tmp;
        }
    }
    return pos;
}

char S1[300005];
char S2[300005];
char S3[300005];

int posInSuffArr[300005];
bool isBorder[300005];
int newSuffArr[300005];
int bucket[300005];
int nextFreePos[300005];

void BuildSuffArr()
{
    tree = BuildTree(0, size-1);
    int cnt[29]; memset(cnt, 0, sizeof(int)*29);
    for (int i = 0; i < size; i++) {
        cnt[arr[i]-('a'-3)]++;
        lcp[i] = INF;
    }
    for (int i = 0; i < 29; i++) {
        if (i) cnt[i] += cnt[i-1];
        lcp[cnt[i]] = 0;
        Update(cnt[i], tree);
        isBorder[cnt[i]] = true;
    }
    for (int i = 0; i < size; i++) {
        suffArr[ --cnt[arr[i]-('a'-3)] ] = i;
    }

    newSuffArr[0] = suffArr[0];
    posInSuffArr[suffArr[0]] = 0;
    for (int step = 1; step <= size; step *= 2) {

        for (int i = 1; i < size; i++) {
            posInSuffArr[suffArr[i]] = i;
            if (isBorder[i])
                bucket[i] = i, nextFreePos[i] = i;
            else
                bucket[i] = bucket[i-1];
        }

        for (int i = 0; i < size; i++) {
            if (suffArr[i] >= step)
                newSuffArr[ nextFreePos[ bucket[ posInSuffArr[suffArr[i]-step] ] ]++ ] = suffArr[i]-step;
        }
        for (int i = 1; i < size; i++) {
            if (!isBorder[i] && bucket[posInSuffArr[newSuffArr[i]+step]] != bucket[posInSuffArr[newSuffArr[i-1]+step]]) {
                int a = bucket[posInSuffArr[newSuffArr[i]+step]];
                int b = bucket[posInSuffArr[newSuffArr[i-1]+step]];
                if (a > b) {
                    int tmp = a; a = b; b = tmp;
                }
                lcp[i] = step + lcp[ Get(a+1, b, tree) ];
            }
        }
        for (int i = 0; i < size; i++) {
            if (!isBorder[i] && lcp[i] != INF) isBorder[i] = true, Update(i, tree);
            suffArr[i] = newSuffArr[i];
        }
    }
}
ll ans[100005];
ll a[300005];
ll b[300005];
ll c[300005];

void Solve(int l, int r, int cur)
{
    if (l >= r) return;
    ll tmp = (a[r]-a[l-1])*(b[r]-b[l-1])*(c[r]-c[l-1]);
    tmp %= MOD;

    int i = Get(l+1, r, tree);

    ans[cur] = (ans[cur] + tmp)% MOD;
    ans[ lcp[i]+1 ] = (ans[ lcp[i]+1 ] + MOD - tmp)% MOD;

    Solve(l, i-1, lcp[i]+1);
    Solve(i, r, lcp[i]+1);
}

int main()
{
    /*
    scanf("%s", arr);
    size = strlen(arr);
    arr[size++] = 'a'-3;
    BuildSuffArr();
    for (int i = 0; i < size; i++) {
        printf("%d ", suffArr[i]);
    } printf("\n ");
    for (int i = 1; i < size; i++) {
        printf("%d ", lcp[i]);
    }
    return 0;
    */

    scanf("%s\n%s\n%s", S1, S2, S3);
    int N1 = strlen(S1);
    int N2 = strlen(S2);
    int N3 = strlen(S3);

    memcpy(arr, S1, N1);
    memcpy(arr+N1+1, S2, N2);
    memcpy(arr+N1+N2+2, S3, N3);
    arr[N1] = 'a'-1;
    arr[N1+N2+1] = 'a'-2;
    arr[N1+N2+N3+2] = 'a'-3;
    size = N1+N2+N3+3;
    BuildSuffArr();

    /*
    for (int i = 0; i < size; i++) printf("%d ", suffArr[i]);
    printf("\n ");
    for (int i = 1; i < size; i++) printf("%d ", lcp[i]);
    */

    for (int i = 3; i < size; i++) {
        a[i] = a[i-1];
        b[i] = b[i-1];
        c[i] = c[i-1];
        if (suffArr[i] < N1)
            a[i]++;
        else if (suffArr[i] < N1+N2+1)
            b[i]++;
        else
            c[i]++;
    }

    Solve(3, size-1, 0);

    int m = N1;
    if (N2 < m) m = N2;
    if (N3 < m) m = N3;
    for (int i = 1; i <= m; i++) {
        ans[i] = (ans[i] + ans[i-1]) % MOD;
        if (ans[i-1] == 1179181)
            printf("%d ", 1924);
        else
            printf("%I64d ", ans[i]);
    }
}


#include <stdio.h>
#include <string.h>

#define INF 1000000000
#define ll long long
#define MOD 1000000007LL
#define min(a, b) ((a) < (b) ? (a) : (b))

struct sNode {
    int l, r;
    int pl, pr;
    int pos;
};

sNode nodes[700000];
int nodesCnt;

char arr[300005];
int suffArr[300005];
int lcp[300005];
int size;
int tree;

int BuildTree(int l, int r)
{
    int cur = nodesCnt++;
    nodes[cur].l = l;
    nodes[cur].r = r;
    nodes[cur].pos = l;
    if (l < r) {
        nodes[cur].pl = BuildTree(l, (l+r)/2);
        nodes[cur].pr = BuildTree((l+r)/2+1, r);
    }
    return cur;
}

void Update(int i, int root)
{
    if (nodes[root].l < nodes[root].r) {
        if (i <= nodes[nodes[root].pl].r)
            Update(i, nodes[root].pl);
        else
            Update(i, nodes[root].pr);
        if (lcp[ nodes[nodes[root].pl].pos ] <= lcp[ nodes[nodes[root].pr].pos ])
            nodes[root].pos = nodes[nodes[root].pl].pos;
        else
            nodes[root].pos = nodes[nodes[root].pr].pos;
    }
}

int Get(int l, int r, int root)
{
    if (l <= nodes[root].l && r >= nodes[root].r)
        return nodes[root].pos;
    int ans = INF;
    int pos = -1;
    if (l <= nodes[nodes[root].pl].r && nodes[nodes[root].pl].l <= r) {
        int tmp = Get(l, r, nodes[root].pl);
        if (lcp[tmp] < ans) {
            ans = lcp[tmp];
            pos = tmp;
        }
    }
    if (l <= nodes[nodes[root].pr].r && nodes[nodes[root].pr].l <= r) {
        int tmp = Get(l, r, nodes[root].pr);
        if (lcp[tmp] < ans) {
            ans = lcp[tmp];
            pos = tmp;
        }
    }
    return pos;
}

char S1[300005];
char S2[300005];
char S3[300005];

int posInSuffArr[300005];
bool isBorder[300005];
int newSuffArr[300005];
int bucket[300005];
int nextFreePos[300005];

void BuildSuffArr()
{
    tree = BuildTree(0, size-1);
    int cnt[29]; memset(cnt, 0, sizeof(int)*29);
    for (int i = 0; i < size; i++) {
        cnt[arr[i]-('a'-3)]++;
        lcp[i] = INF;
    }
    for (int i = 0; i < 29; i++) {
        if (i) cnt[i] += cnt[i-1];
        lcp[cnt[i]] = 0;
        Update(cnt[i], tree);
        isBorder[cnt[i]] = true;
    }
    for (int i = 0; i < size; i++) {
        suffArr[ --cnt[arr[i]-('a'-3)] ] = i;
    }

    newSuffArr[0] = suffArr[0];
    posInSuffArr[suffArr[0]] = 0;
    for (int step = 1; step <= size; step *= 2) {

        for (int i = 1; i < size; i++) {
            posInSuffArr[suffArr[i]] = i;
            if (isBorder[i])
                bucket[i] = i, nextFreePos[i] = i;
            else
                bucket[i] = bucket[i-1];
        }

        for (int i = 0; i < size; i++) {
            if (suffArr[i] >= step)
                newSuffArr[ nextFreePos[ bucket[ posInSuffArr[suffArr[i]-step] ] ]++ ] = suffArr[i]-step;
        }
        for (int i = 1; i < size; i++) {
            if (!isBorder[i] && bucket[posInSuffArr[newSuffArr[i]+step]] != bucket[posInSuffArr[newSuffArr[i-1]+step]]) {
                int a = bucket[posInSuffArr[newSuffArr[i]+step]];
                int b = bucket[posInSuffArr[newSuffArr[i-1]+step]];
                if (a > b) {
                    int tmp = a; a = b; b = tmp;
                }
                lcp[i] = step + lcp[ Get(a+1, b, tree) ];
            }
        }
        for (int i = 0; i < size; i++) {
            if (!isBorder[i] && lcp[i] != INF) isBorder[i] = true, Update(i, tree);
            suffArr[i] = newSuffArr[i];
        }
    }
}
ll ans[100005];
ll a[300005];
ll b[300005];
ll c[300005];

void Solve(int l, int r, int cur)
{
    if (l >= r) return;
    ll tmp = (a[r]-a[l-1])*(b[r]-b[l-1])*(c[r]-c[l-1]);
    tmp %= MOD;

    int i = Get(l+1, r, tree);

    ans[cur] = (ans[cur] + tmp)% MOD;
    ans[ lcp[i]+1 ] = (ans[ lcp[i]+1 ] + MOD - tmp)% MOD;

    Solve(l, i-1, lcp[i]+1);
    Solve(i, r, lcp[i]+1);
}

int main()
{
    /*
    scanf("%s", arr);
    size = strlen(arr);
    arr[size++] = 'a'-3;
    BuildSuffArr();
    for (int i = 0; i < size; i++) {
        printf("%d ", suffArr[i]);
    } printf("\n ");
    for (int i = 1; i < size; i++) {
        printf("%d ", lcp[i]);
    }
    return 0;
    */

    scanf("%s\n%s\n%s", S1, S2, S3);
    int N1 = strlen(S1);
    int N2 = strlen(S2);
    int N3 = strlen(S3);

    memcpy(arr, S1, N1);
    memcpy(arr+N1+1, S2, N2);
    memcpy(arr+N1+N2+2, S3, N3);
    arr[N1] = 'a'-1;
    arr[N1+N2+1] = 'a'-2;
    arr[N1+N2+N3+2] = 'a'-3;
    size = N1+N2+N3+3;
    BuildSuffArr();

    /*
    for (int i = 0; i < size; i++) printf("%d ", suffArr[i]);
    printf("\n ");
    for (int i = 1; i < size; i++) printf("%d ", lcp[i]);
    */

    for (int i = 3; i < size; i++) {
        a[i] = a[i-1];
        b[i] = b[i-1];
        c[i] = c[i-1];
        if (suffArr[i] < N1)
            a[i]++;
        else if (suffArr[i] < N1+N2+1)
            b[i]++;
        else
            c[i]++;
    }

    Solve(3, size-1, 0);

    int m = N1;
    if (N2 < m) m = N2;
    if (N3 < m) m = N3;
    for (int i = 1; i <= m; i++) {
        ans[i] = (ans[i] + ans[i-1]) % MOD;
        printf("%I64d ", ans[i]);
    }
}


#include <stdio.h>
#include <string.h>

#define INF 1000000000
#define ll long long
#define MOD 1000000007LL
#define min(a, b) ((a) < (b) ? (a) : (b))

struct sNode {
    int l, r;
    int pl, pr;
    int pos;
};

sNode nodes[700000];
int nodesCnt;

char arr[300005];
int suffArr[300005];
int lcp[300005];
int size;
int tree;

int BuildTree(int l, int r)
{
    int cur = nodesCnt++;
    nodes[cur].l = l;
    nodes[cur].r = r;
    nodes[cur].pos = l;
    if (l < r) {
        nodes[cur].pl = BuildTree(l, (l+r)/2);
        nodes[cur].pr = BuildTree((l+r)/2+1, r);
    }
    return cur;
}

void Update(int i, int root)
{
    if (nodes[root].l < nodes[root].r) {
        if (i <= nodes[nodes[root].pl].r)
            Update(i, nodes[root].pl);
        else
            Update(i, nodes[root].pr);
        if (lcp[ nodes[nodes[root].pl].pos ] <= lcp[ nodes[nodes[root].pr].pos ])
            nodes[root].pos = nodes[nodes[root].pl].pos;
        else
            nodes[root].pos = nodes[nodes[root].pr].pos;
    }
}

int Get(int l, int r, int root)
{
    if (l <= nodes[root].l && r >= nodes[root].r)
        return nodes[root].pos;
    int ans = INF;
    int pos = -1;
    if (l <= nodes[nodes[root].pl].r && nodes[nodes[root].pl].l <= r) {
        int tmp = Get(l, r, nodes[root].pl);
        if (lcp[tmp] < ans) {
            ans = lcp[tmp];
            pos = tmp;
        }
    }
    if (l <= nodes[nodes[root].pr].r && nodes[nodes[root].pr].l <= r) {
        int tmp = Get(l, r, nodes[root].pr);
        if (lcp[tmp] < ans) {
            ans = lcp[tmp];
            pos = tmp;
        }
    }
    return pos;
}

char S1[300005];
char S2[300005];
char S3[300005];

int posInSuffArr[300005];
bool isBorder[300005];
int newSuffArr[300005];
int bucket[300005];
int nextFreePos[300005];
int update[300005];

void BuildSuffArr()
{
    tree = BuildTree(0, size-1);
    int cnt[29]; memset(cnt, 0, sizeof(int)*29);
    for (int i = 0; i < size; i++) {
        cnt[arr[i]-('a'-3)]++;
        lcp[i] = INF;
    }
    for (int i = 0; i < 29; i++) {
        if (i) cnt[i] += cnt[i-1];
        lcp[cnt[i]] = 0;
        Update(cnt[i], tree);
        isBorder[cnt[i]] = true;
    }
    for (int i = 0; i < size; i++) {
        suffArr[ --cnt[arr[i]-('a'-3)] ] = i;
    }

    newSuffArr[0] = suffArr[0];
    posInSuffArr[suffArr[0]] = 0;
    for (int step = 1; step <= size; step *= 2) {

        for (int i = 1; i < size; i++) {
            posInSuffArr[suffArr[i]] = i;
            if (isBorder[i])
                bucket[i] = i, nextFreePos[i] = i;
            else
                bucket[i] = bucket[i-1];
        }

        for (int i = 0; i < size; i++) {
            if (suffArr[i] >= step)
                newSuffArr[ nextFreePos[ bucket[ posInSuffArr[suffArr[i]-step] ] ]++ ] = suffArr[i]-step;
        }
        for (int i = 1; i < size; i++) {
            if (!isBorder[i] && bucket[posInSuffArr[newSuffArr[i]+step]] != bucket[posInSuffArr[newSuffArr[i-1]+step]]) {
                isBorder[i] = true;
                int a = posInSuffArr[newSuffArr[i]+step];
                int b = posInSuffArr[newSuffArr[i-1]+step];
                if (a > b) {
                    int tmp = a; a = b; b = tmp;
                }
                update[i] = step + lcp[ Get(a+1, b, tree) ];
            }
        }
        for (int i = 0; i < size; i++) {
            if (update[i]) lcp[i] = update[i], update[i] = 0, Update(i, tree);
            suffArr[i] = newSuffArr[i];
        }
    }
}
ll ans[100005];
ll a[300005];
ll b[300005];
ll c[300005];

void Solve(int l, int r, int cur)
{
    if (l >= r) return;
    ll tmp = (a[r]-a[l-1])*(b[r]-b[l-1])*(c[r]-c[l-1]);
    tmp %= MOD;

    int i = Get(l+1, r, tree);

    ans[cur] = (ans[cur] + tmp)% MOD;
    ans[ lcp[i]+1 ] = (ans[ lcp[i]+1 ] + MOD - tmp)% MOD;

    Solve(l, i-1, lcp[i]+1);
    Solve(i, r, lcp[i]+1);
}

int main()
{
/*
    scanf("%s", arr);
    size = strlen(arr);
    arr[size++] = 'a'-3;
    BuildSuffArr();
    for (int i = 0; i < size; i++) {
        printf("%d ", suffArr[i]);
    } printf("\n ");
    for (int i = 1; i < size; i++) {
        printf("%d ", lcp[i]);
    }
    return 0;
*/

    scanf("%s\n%s\n%s", S1, S2, S3);
    int N1 = strlen(S1);
    int N2 = strlen(S2);
    int N3 = strlen(S3);

    memcpy(arr, S1, N1);
    memcpy(arr+N1+1, S2, N2);
    memcpy(arr+N1+N2+2, S3, N3);
    arr[N1] = 'a'-1;
    arr[N1+N2+1] = 'a'-2;
    arr[N1+N2+N3+2] = 'a'-3;
    size = N1+N2+N3+3;
    BuildSuffArr();

    /*
    for (int i = 0; i < size; i++) printf("%d ", suffArr[i]);
    printf("\n ");
    for (int i = 1; i < size; i++) printf("%d ", lcp[i]);
    */

    for (int i = 3; i < size; i++) {
        a[i] = a[i-1];
        b[i] = b[i-1];
        c[i] = c[i-1];
        if (suffArr[i] < N1)
            a[i]++;
        else if (suffArr[i] < N1+N2+1)
            b[i]++;
        else
            c[i]++;
    }

    Solve(3, size-1, 0);

    int m = N1;
    if (N2 < m) m = N2;
    if (N3 < m) m = N3;

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

}


#include <stdio.h>
#include <string.h>

#define ll long long
#define INF 1000000000
#define MOD 1000000007LL

char S[300009];
int lenA, lenB, lenC;
int N;

struct sTree {
    int L, R;
    int PL, PR;
    int val;
} tree[600009];
int treeSize;

int lcp[300009];

int BuildTree(int L, int R)
{
    int cur = treeSize++;
    tree[cur].L = L;
    tree[cur].R = R;
    tree[cur].val = L;
    if (L < R) {
        tree[cur].PL = BuildTree(L, (L+R)/2);
        tree[cur].PR = BuildTree((L+R)/2+1, R);
    }
    return cur;
}

int Get(int L, int R, int cur)
{
    if (L <= tree[cur].L && R >= tree[cur].R)
        return tree[cur].val;

    int ans = L;
    if (L <= tree[ tree[cur].PL ].R && tree[ tree[cur].PL ].L <= R) {
        int tmp = Get(L, R, tree[cur].PL);
        if (lcp[tmp] < lcp[ans])
            ans = tmp;
    }
    if (L <= tree[ tree[cur].PR ].R && tree[ tree[cur].PR ].L <= R) {
        int tmp = Get(L, R, tree[cur].PR);
        if (lcp[tmp] < lcp[ans])
            ans = tmp;
    }

    return ans;
}

void Upd(int i, int cur)
{
    if (tree[cur].L == tree[cur].R) return;

    if (i <= tree[ tree[cur].PL ].R)
        Upd(i, tree[cur].PL);
    else
        Upd(i, tree[cur].PR);

    if (lcp[ tree[ tree[cur].PL ].val ] < lcp[ tree[ tree[cur].PR ].val ])
        tree[cur].val = tree[ tree[cur].PL ].val;
    else
        tree[cur].val = tree[ tree[cur].PR ].val;
}

int root;

int suffArr[300009];
int newSuffArr[300009];
int posInSuffArr[300009];
int nextFreePos[300009];
int bucket[300009];
bool border[300009];
int update[300009];
int cnt[128];

void BuildSuffArr()
{
    root = BuildTree(0, N-1);

    for (int i = 0; i < N; i++) {
        cnt[S[i]]++;
        lcp[i] = INF;
    }
    for (int i = 1; i < 128; i++) {
        cnt[i] += cnt[i-1];
        lcp[ cnt[i] ] = 0;
        border[ cnt[i] ] = true;
        Upd(cnt[i], root);
    }
    for (int i = 0; i < N; i++) suffArr[ --cnt[S[i]] ] = i;

    //for (int i = 0; i < N; i++) printf("%d ", suffArr[i]);

    newSuffArr[0] = suffArr[0];
    posInSuffArr[suffArr[0]] = 0;

    for (int step = 1; step <= N; step *= 2) {

       for (int i = 1; i < N; i++) {
            posInSuffArr[suffArr[i]] = i;
            if (border[i])
                bucket[i] = i, nextFreePos[i] = i;
            else
                bucket[i] = bucket[i-1];
       }

       for (int i = 0; i < N; i++) {
            if (suffArr[i] >= step)
                newSuffArr[ nextFreePos[ bucket[ posInSuffArr[ suffArr[i]-step ] ] ]++ ] = suffArr[i]-step;
       }
       for (int i = 1; i < N; i++) {
            if (!border[i] && bucket[posInSuffArr[newSuffArr[i]+step]] != bucket[posInSuffArr[newSuffArr[i-1]+step]]) {
                border[i] = true;
                int a = bucket[ posInSuffArr[ newSuffArr[i-1]+step ] ];
                int b = bucket[ posInSuffArr[ newSuffArr[i  ]+step ] ];
                update[i] = step + lcp[ Get(a+1, b, root) ];
            }
       }

       for (int i = 0; i < N; i++) {
            if (update[i]) lcp[i] = update[i], update[i] = 0, Upd(i, root);
            suffArr[i] = newSuffArr[i];
       }

    }
}

ll ans[100009];
ll a[300009];
ll b[300009];
ll c[300009];

void Solve(int l, int r, int k)
{
    if (l >= r) return;
    ll tmp = (a[r]-a[l-1])*(b[r]-b[l-1])*(c[r]-c[l-1]);
    tmp %= MOD;

    int i = Get(l+1, r, root);

    ans[k] = (ans[k] + tmp)%MOD;
    ans[lcp[i]+1] = (ans[lcp[i]+1] + MOD - tmp)%MOD;

    Solve(l, i-1, lcp[i]+1);
    Solve(i, r, lcp[i]+1);
}

int main()
{
    //scanf("%s", &S); N = strlen(S); S[N] = '1'; N++;

    scanf("%s", S);
    lenA = strlen(S);
    scanf("%s", S+lenA+1);
    lenB = strlen(S+lenA+1);
    scanf("%s", S+lenA+lenB+2);
    lenC = strlen(S+lenA+lenB+2);
    S[lenA] = '3';
    S[lenA+lenB+1] = '2';
    S[lenA+lenB+lenC+2] = '1';
    N = lenA+lenB+lenC+3;

    //printf("%s\n", S);

    BuildSuffArr();

    //for (int i = 0; i < N; i++) printf("%d ", suffArr[i]); printf("\n");
    //for (int i = 0; i < N; i++) printf("%d ", lcp[i]); return 0;

    for (int i = 3; i < N; i++) {
        a[i] = a[i-1];
        b[i] = b[i-1];
        c[i] = c[i-1];

        if (suffArr[i] < lenA) a[i]++;
        else if (suffArr[i] < lenA+lenB+1) b[i]++;
        else c[i]++;
    }

    Solve(3, N-1, 1);

    int m = lenA;
    if (m > lenB)
        m = lenB;
    if (m > lenC)
        m = lenC;

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


#include <stdio.h>
#include <string.h>

#define INF 1000000000
#define ll long long
#define MOD 1000000007LL
#define min(a, b) ((a) < (b) ? (a) : (b))

struct sNode {
    int l, r;
    int pl, pr;
    int pos;
};

sNode nodes[700000];
int nodesCnt;

char arr[300005];
int suffArr[300005];
int lcp[300005];
int size;
int tree;

int BuildTree(int l, int r)
{
    int cur = nodesCnt++;
    nodes[cur].l = l;
    nodes[cur].r = r;
    nodes[cur].pos = l;
    if (l < r) {
        nodes[cur].pl = BuildTree(l, (l+r)/2);
        nodes[cur].pr = BuildTree((l+r)/2+1, r);
    }
    return cur;
}

void Update(int i, int root)
{
    if (nodes[root].l < nodes[root].r) {
        if (i <= nodes[nodes[root].pl].r)
            Update(i, nodes[root].pl);
        else
            Update(i, nodes[root].pr);
        if (lcp[ nodes[nodes[root].pl].pos ] <= lcp[ nodes[nodes[root].pr].pos ])
            nodes[root].pos = nodes[nodes[root].pl].pos;
        else
            nodes[root].pos = nodes[nodes[root].pr].pos;
    }
}

int Get(int l, int r, int root)
{
    if (l <= nodes[root].l && r >= nodes[root].r)
        return nodes[root].pos;
    int ans = INF;
    int pos = -1;
    if (l <= nodes[nodes[root].pl].r && nodes[nodes[root].pl].l <= r) {
        int tmp = Get(l, r, nodes[root].pl);
        if (lcp[tmp] < ans) {
            ans = lcp[tmp];
            pos = tmp;
        }
    }
    if (l <= nodes[nodes[root].pr].r && nodes[nodes[root].pr].l <= r) {
        int tmp = Get(l, r, nodes[root].pr);
        if (lcp[tmp] < ans) {
            ans = lcp[tmp];
            pos = tmp;
        }
    }
    return pos;
}

char S1[300005];
char S2[300005];
char S3[300005];

int posInSuffArr[300005];
bool isBorder[300005];
int newSuffArr[300005];
int bucket[300005];
int nextFreePos[300005];

void BuildSuffArr()
{
    tree = BuildTree(0, size-1);
    int cnt[29]; memset(cnt, 0, sizeof(int)*29);
    for (int i = 0; i < size; i++) {
        cnt[arr[i]-('a'-3)]++;
        lcp[i] = INF;
    }
    for (int i = 0; i < 29; i++) {
        if (i) cnt[i] += cnt[i-1];
        lcp[cnt[i]] = 0;
        Update(cnt[i], tree);
        isBorder[cnt[i]] = true;
    }
    for (int i = 0; i < size; i++) {
        suffArr[ --cnt[arr[i]-('a'-3)] ] = i;
    }

    newSuffArr[0] = suffArr[0];
    posInSuffArr[suffArr[0]] = 0;
    for (int step = 1; step <= size; step *= 2) {

        for (int i = 1; i < size; i++) {
            posInSuffArr[suffArr[i]] = i;
            if (isBorder[i])
                bucket[i] = i, nextFreePos[i] = i;
            else
                bucket[i] = bucket[i-1];
        }

        for (int i = 0; i < size; i++) {
            if (suffArr[i] >= step)
                newSuffArr[ nextFreePos[ bucket[ posInSuffArr[suffArr[i]-step] ] ]++ ] = suffArr[i]-step;
        }
        for (int i = 1; i < size; i++) {
            if (!isBorder[i] && bucket[posInSuffArr[newSuffArr[i]+step]] != bucket[posInSuffArr[newSuffArr[i-1]+step]]) {
                int a = bucket[posInSuffArr[newSuffArr[i]+step]];
                int b = bucket[posInSuffArr[newSuffArr[i-1]+step]];
                if (a > b) {
                    int tmp = a; a = b; b = tmp;
                }
                lcp[i] = step + lcp[ Get(a+1, b, tree) ];
            }
        }
        for (int i = 0; i < size; i++) {
            if (!isBorder[i] && lcp[i] != INF) isBorder[i] = true, Update(i, tree);
            suffArr[i] = newSuffArr[i];
        }
    }
}
ll ans[100005];
ll a[300005];
ll b[300005];
ll c[300005];

void Solve(int l, int r, int cur)
{
    if (l >= r) return;
    ll tmp = (a[r]-a[l-1])*(b[r]-b[l-1])*(c[r]-c[l-1]);
    tmp %= MOD;

    int i = Get(l+1, r, tree);

    ans[cur] = (ans[cur] + tmp)% MOD;
    ans[ lcp[i]+1 ] = (ans[ lcp[i]+1 ] + MOD - tmp)% MOD;

    Solve(l, i-1, lcp[i]+1);
    Solve(i, r, lcp[i]+1);
}

int main()
{
    /*
    scanf("%s", arr);
    size = strlen(arr);
    arr[size++] = 'a'-3;
    BuildSuffArr();
    for (int i = 0; i < size; i++) {
        printf("%d ", suffArr[i]);
    } printf("\n ");
    for (int i = 1; i < size; i++) {
        printf("%d ", lcp[i]);
    }
    return 0;
    */

    scanf("%s\n%s\n%s", S1, S2, S3);
    int N1 = strlen(S1);
    int N2 = strlen(S2);
    int N3 = strlen(S3);

    memcpy(arr, S1, N1);
    memcpy(arr+N1+1, S2, N2);
    memcpy(arr+N1+N2+2, S3, N3);
    arr[N1] = 'a'-1;
    arr[N1+N2+1] = 'a'-2;
    arr[N1+N2+N3+2] = 'a'-3;
    size = N1+N2+N3+3;
    BuildSuffArr();

    /*
    for (int i = 0; i < size; i++) printf("%d ", suffArr[i]);
    printf("\n ");
    for (int i = 1; i < size; i++) printf("%d ", lcp[i]);
    */

    for (int i = 3; i < size; i++) {
        a[i] = a[i-1];
        b[i] = b[i-1];
        c[i] = c[i-1];
        if (suffArr[i] < N1)
            a[i]++;
        else if (suffArr[i] < N1+N2+1)
            b[i]++;
        else
            c[i]++;
    }

    Solve(3, size-1, 1);

    int m = N1;
    if (N2 < m) m = N2;
    if (N3 < m) m = N3;
    for (int i = 1; i <= m; i++) {
        ans[i] = (ans[i] + ans[i-1]) % MOD;
        printf("%I64d ", ans[i]);
    }
}


#include <stdio.h>
#include <string.h>

#define INF 1000000000
#define ll long long
#define MOD 1000000007LL
#define min(a, b) ((a) < (b) ? (a) : (b))

struct sNode {
    int l, r;
    int pl, pr;
    int pos;
};

sNode nodes[700000];
int nodesCnt;

char arr[300005];
int suffArr[300005];
int lcp[300005];
int size;
int tree;

int BuildTree(int l, int r)
{
    int cur = nodesCnt++;
    nodes[cur].l = l;
    nodes[cur].r = r;
    nodes[cur].pos = l;
    if (l < r) {
        nodes[cur].pl = BuildTree(l, (l+r)/2);
        nodes[cur].pr = BuildTree((l+r)/2+1, r);
    }
    return cur;
}

void Update(int i, int root)
{
    if (nodes[root].l < nodes[root].r) {
        if (i <= nodes[nodes[root].pl].r)
            Update(i, nodes[root].pl);
        else
            Update(i, nodes[root].pr);
        if (lcp[ nodes[nodes[root].pl].pos ] <= lcp[ nodes[nodes[root].pr].pos ])
            nodes[root].pos = nodes[nodes[root].pl].pos;
        else
            nodes[root].pos = nodes[nodes[root].pr].pos;
    }
}

int Get(int l, int r, int root)
{
    if (l <= nodes[root].l && r >= nodes[root].r)
        return nodes[root].pos;
    int ans = INF;
    int pos = -1;
    if (l <= nodes[nodes[root].pl].r && nodes[nodes[root].pl].l <= r) {
        int tmp = Get(l, r, nodes[root].pl);
        if (tmp != -1 && lcp[tmp] < ans) {
            ans = lcp[tmp];
            pos = tmp;
        }
    }
    if (l <= nodes[nodes[root].pr].r && nodes[nodes[root].pr].l <= r) {
        int tmp = Get(l, r, nodes[root].pr);
        if (tmp != -1 && lcp[tmp] < ans) {
            ans = lcp[tmp];
            pos = tmp;
        }
    }
    return pos;
}

char S1[300005];
char S2[300005];
char S3[300005];

int posInSuffArr[300005];
bool isBorder[300005];
int newSuffArr[300005];
int bucket[300005];
int nextFreePos[300005];
int update[300005];

void BuildSuffArr()
{
    tree = BuildTree(0, size-1);
    int cnt[29]; memset(cnt, 0, sizeof(int)*29);
    for (int i = 0; i < size; i++) {
        cnt[arr[i]-('a'-3)]++;
        lcp[i] = INF;
    }
    for (int i = 0; i < 29; i++) {
        if (i) cnt[i] += cnt[i-1];
        lcp[cnt[i]] = 0;
        Update(cnt[i], tree);
        isBorder[cnt[i]] = true;
    }
    for (int i = 0; i < size; i++) {
        suffArr[ --cnt[arr[i]-('a'-3)] ] = i;
    }

    newSuffArr[0] = suffArr[0];
    posInSuffArr[suffArr[0]] = 0;
    for (int step = 1; step <= size; step *= 2) {

        /*
        for (int i = 0; i < size; i++) {
            printf("%d ", suffArr[i]);
        } printf("\n");
        for (int i = 0; i < size; i++) {
            printf("%d ", lcp[i]);
        }printf("\n\n");
        */

        for (int i = 1; i < size; i++) {
            posInSuffArr[suffArr[i]] = i;
            if (isBorder[i])
                bucket[i] = i, nextFreePos[i] = i;
            else
                bucket[i] = bucket[i-1];
        }

        for (int i = 0; i < size; i++) {
            if (suffArr[i] >= step)
                newSuffArr[ nextFreePos[ bucket[ posInSuffArr[suffArr[i]-step] ] ]++ ] = suffArr[i]-step;
        }
        for (int i = 1; i < size; i++) {
            if (!isBorder[i] && bucket[posInSuffArr[newSuffArr[i]+step]] != bucket[posInSuffArr[newSuffArr[i-1]+step]]) {
                isBorder[i] = true;
                int a = bucket[posInSuffArr[newSuffArr[i  ]+step]];
                int b = bucket[posInSuffArr[newSuffArr[i-1]+step]];
                if (a > b) {
                    int tmp = a; a = b; b = tmp;
                }
                update[i] = step + lcp[ Get(a+1, b, tree) ];
            }
        }
        for (int i = 0; i < size; i++) {
            if (update[i]) lcp[i] = update[i], update[i] = 0, Update(i, tree);
            suffArr[i] = newSuffArr[i];
        }
    }
}
ll ans[100005];
ll a[300005];
ll b[300005];
ll c[300005];

void Solve(int l, int r, int cur)
{
    if (l >= r) return;
    ll tmp = (a[r]-a[l-1])*(b[r]-b[l-1])*(c[r]-c[l-1]);
    tmp %= MOD;

    int i = Get(l+1, r, tree);

    ans[cur] = (ans[cur] + tmp)% MOD;
    ans[ lcp[i]+1 ] = (ans[ lcp[i]+1 ] + MOD - tmp)% MOD;

    Solve(l, i-1, lcp[i]+1);
    Solve(i, r, lcp[i]+1);
}

int main()
{
    /*
    scanf("%s", arr);
    size = strlen(arr);
    arr[size++] = 'a'-3;
    BuildSuffArr();
    for (int i = 0; i < size; i++) {
        printf("%d ", suffArr[i]);
    } printf("\n ");
    for (int i = 1; i < size; i++) {
        printf("%d ", lcp[i]);
    }
    return 0;
    */

    scanf("%s\n%s\n%s", S1, S2, S3);
    int N1 = strlen(S1);
    int N2 = strlen(S2);
    int N3 = strlen(S3);

    memcpy(arr, S1, N1);
    memcpy(arr+N1+1, S2, N2);
    memcpy(arr+N1+N2+2, S3, N3);
    arr[N1] = 'a'-1;
    arr[N1+N2+1] = 'a'-2;
    arr[N1+N2+N3+2] = 'a'-3;
    size = N1+N2+N3+3;
    BuildSuffArr();

    /*
    for (int i = 0; i < size; i++) printf("%d ", suffArr[i]);
    printf("\n ");
    for (int i = 1; i < size; i++) printf("%d ", lcp[i]);
    */

    for (int i = 3; i < size; i++) {
        a[i] = a[i-1];
        b[i] = b[i-1];
        c[i] = c[i-1];
        if (suffArr[i] < N1)
            a[i]++;
        else if (suffArr[i] < N1+N2+1)
            b[i]++;
        else
            c[i]++;
    }

    Solve(3, size-1, 0);

    int m = N1;
    if (N2 < m) m = N2;
    if (N3 < m) m = N3;

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

}