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;
}