| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 
 | #include <iostream>#include <cstring>
 #include <vector>
 #include <algorithm>
 #define maxn 300010
 #define ll long long
 using namespace std;
 
 const int p = 1000000007;
 
 int n, m, k, len;
 char c[maxn], s[maxn];
 
 int tax[maxn], tp[maxn], sa[maxn], rk[maxn], M = 255;
 void rsort(int n) {
 for (int i = 0; i <= M; ++i) tax[i] = 0;
 for (int i = 1; i <= n; ++i) ++tax[rk[i]];
 for (int i = 1; i <= M; ++i) tax[i] += tax[i - 1];
 for (int i = n; i; --i) sa[tax[rk[tp[i]]]--] = tp[i];
 }
 
 int H[maxn];
 void init_sa(int n) {
 if (n == 1) return sa[1] = rk[1] = 1, void(); int cnt = 1;
 for (int i = 1; i <= n; ++i) rk[i] = s[i], tp[i] = i; rsort(n);
 for (int k = 1; k < n; k *= 2) {
 if (cnt == n) break; M = cnt; cnt = 0;
 for (int i = n - k + 1; i <= n; ++i) tp[++cnt] = i;
 for (int i = 1; i <= n; ++i) if (sa[i] > k) tp[++cnt] = sa[i] - k;
 rsort(n); swap(rk, tp); rk[sa[1]] = cnt = 1;
 for (int i = 2; i <= n; ++i) {
 if (tp[sa[i - 1]] != tp[sa[i]] || tp[sa[i - 1] + k] != tp[sa[i] + k]) ++cnt;
 rk[sa[i]] = cnt;
 }
 } int lcp = 0;
 for (int i = 1; i <= n; ++i) {
 if (lcp) --lcp;
 int j = sa[rk[i] - 1];
 while (s[j + lcp] == s[i + lcp]) ++lcp;
 H[rk[i]] = lcp;
 }
 }
 
 int bl[maxn];
 vector<int> A[maxn];
 
 int fa[maxn], f[maxn][4], g[maxn];
 void init_fa(int n) { for (int i = 1; i <= n; ++i) fa[i] = i, f[i][bl[i]] = 1; }
 
 int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
 
 ll res;
 inline void merge(int x, int y) {
 int fx = find(x), fy = find(y);
 if (fx == fy) return ;
 fa[fy] = fx; res = (res - g[fx] - g[fy]) % p;
 for (int i = 1; i <= 3; ++i) f[fx][i] += f[fy][i];
 g[fx] = 1ll * f[fx][1] * f[fx][2] % p * f[fx][3] % p;
 res = (res + g[fx]) % p;
 }
 
 int ans[maxn];
 int main() {
 ios::sync_with_stdio(false);
 cin.tie(nullptr); cout.tie(nullptr);
 
 cin >> c; n = strlen(c);
 cin >> c + n; m = strlen(c + n);
 cin >> c + n + m; k = strlen(c + n + m);
 for (int i = 0; i < n; ++i) s[++len] = c[i], bl[len] = 1; s[++len] = '$';
 for (int i = n; i < n + m; ++i) s[++len] = c[i], bl[len] = 2; s[++len] = '#';
 for (int i = n + m; i < n + m + k; ++i) s[++len] = c[i], bl[len] = 3; init_sa(len);
 for (int i = 1; i <= len; ++i) A[H[i]].push_back(i); init_fa(len);
 for (int l = len; l; --l) {
 for (auto t : A[l]) merge(sa[t - 1], sa[t]);
 ans[l] = res;
 }
 for (int i = 1; i <= min({ n, m, k }); ++i) cout << (ans[i] + p) % p << " ";
 return 0;
 }
 
 
 |