You are given three strings (s 1, s 2, s 3). For each integer l (1 ≤ l ≤ min(|s 1|, |s 2|, |s 3|) you need to find how many triples ( i 1, i 2, i 3) exist such that three strings s k[i k… i k + l - 1] (k = 1, 2, 3) are pairwise equal. Print all found numbers modulo 1000000007 (109 + 7).
See notes if you are not sure about some of the denotions used in the statement.
Input
First three lines contain three non-empty input strings. The sum of lengths of all strings is no more than 3·105. All strings consist only of lowercase English letters.
Output
You need to output min(|s 1|, |s 2|, |s 3|) numbers separated by spaces — answers for the problem modulo 1000000007 (109 + 7).
Examples
input
abc
bc
cbc
output
3 1
input
abacaba
abac
abcd
output
11 2 0 0
Note
Consider a string t = t 1 t 2… t |t|, where t i denotes the i-th character of the string, and |t| denotes the length of the string.
Then t[i… j] (1 ≤ i ≤ j ≤ |t|) represents the string t i t i + 1… t j (substring of t from position i to position j inclusive).
Solution:
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <memory.h> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> using namespace std; const int md = 1000000007; const int N = 600010; int last[N], pred[N]; pair <int, int> t[N]; char s[N]; int a[N], g[N], pz[N]; int nna[N], ng[N]; int d[25][N]; int lcp[N]; int sum[N][3]; void subtr(int &ans, int *x, int *y) { int u = x[0] - y[0]; for (int j = 1; j < 3; j++) { int v = x[j] - y[j]; u = (long long)u * v % md; } ans += md - u; if (ans >= md) { ans -= md; } } void add(int &ans, int *x, int *y) { int u = x[0] - y[0]; for (int j = 1; j < 3; j++) { int v = x[j] - y[j]; u = (long long)u * v % md; } ans += u; if (ans >= md) { ans -= md; } } char sa[N], sb[N], sc[N]; int type[N]; int pr[N], ne[N]; int result[N]; int main() { scanf("%s", sa); scanf("%s", sb); scanf("%s", sc); int na = strlen(sa); int nb = strlen(sb); int nc = strlen(sc); for (int i = 1; i <= na; i++) { s[i] = sa[i - 1]; type[i] = 0; } s[na + 1] = '#'; type[na + 1] = -1; for (int i = na + 2; i <= na + nb + 1; i++) { s[i] = sb[i - na - 2]; type[i] = 1; } s[na + nb + 2] = '$'; type[na + nb + 2] = -1; for (int i = na + nb + 3; i <= na + nb + nc + 2; i++) { s[i] = sc[i - na - nb - 3]; type[i] = 2; } s[na + nb + nc + 3] = 0; int n = strlen(s + 1); for (int c = 0; c < 255; c++) last = 0; for (int i = 1; i <= n; i++) { pred[i] = last[s[i]]; last[s[i]] = i; } int kg = 0, nn = 0; for (int c = 0; c < 255; c++) if (last > 0) { kg++; int j = last; while (j > 0) { nn++; a[nn] = j; g[nn] = kg; pz[j] = nn; j = pred[j]; } } int it = 0, step = 1; while (kg < n) { for (int i = 1; i <= n; i++) d[it][i] = g[pz[i]]; it++; int nkg = 0; int beg = 1; while (beg <= n) { int end = beg; while (end + 1 <= n && g[end + 1] == g[beg]) { end++; } for (int i = beg; i <= end; i++) { int p = a[i] + step; t[i] = make_pair((p > n ? 0 : g[pz[p]]), a[i]); } sort(t + beg, t + end + 1); for (int i = beg; i <= end; i++) { if (i == beg || t[i].first != t[i - 1].first) { nkg++; } nna[i] = t[i].second; ng[i] = nkg; } beg = end + 1; } kg = nkg; for (int i = 1; i <= n; i++) { a[i] = nna[i]; g[i] = ng[i]; pz[a[i]] = i; } step <<= 1; } for (int i = 1; i <= n - 1; i++) { int v = 0; for (int j = it - 1; j >= 0; j--) if (a[i] + v <= n && a[i + 1] + v <= n && d[j][a[i] + v] == d[j][a[i + 1] + v]) { v += (1 << j); } lcp[i] = v; } for (int j = 0; j < 3; j++) { sum[0][j] = 0; } for (int i = 1; i <= n; i++) { for (int j = 0; j < 3; j++) { sum[i][j] = sum[i - 1][j]; } if (type[a[i]] != -1) { sum[i][type[a[i]]]++; } } for (int i = 0; i <= n; i++) { last[i] = 0; } for (int i = 1; i <= n - 1; i++) { pred[i] = last[lcp[i]]; last[lcp[i]] = i; } for (int i = 0; i <= n; i++) { pr[i] = i - 1; ne[i] = i + 1; } int ans = 0; for (int word = n - 1; word >= 1; word--) { int j = last[word]; while (j > 0) { subtr(ans, sum[j], sum[pr[j]]); subtr(ans, sum[ne[j]], sum[j]); add(ans, sum[ne[j]], sum[pr[j]]); pr[ne[j]] = pr[j]; ne[pr[j]] = ne[j]; j = pred[j]; } result[word] = ans; } int len = min(min(na, nb), nc); for (int i = 1; i < len; i++) { printf("%d ", result[i]); } printf("%d\n", result[len]); return 0; }