卧薪尝胆,厚积薄发。
Three strings
Date: Sun Feb 24 09:43:07 CST 2019 In Category: NoCategory

Description:

给三个字符串,对于每个 $L$ ,求出 $S_1[i,i+L-1]=S_2[j,j+L-1]=S_3[k,k+L-1]$ 的个数。
$1\leqslant n\leqslant 3\times 10^5$

Solution:

显然对于广义后缀自动机上的每个节点的贡献是 $siz_1[k]\times siz_2[k]\times siz_3[k]$ ,于是差分一下就做完了。

Code:


#include<bits/stdc++.h>
using namespace std;
#define MAXN 600010
#define MOD 1000000007
char c[MAXN];
struct node
{
int tr[26];
int par,maxl;
}s[MAXN];
int ptr = 1,root = 1,last = 1;
int newnode(int l){int k = ++ptr;s[k].maxl = l;return k;}
int siz[MAXN][3];
void extend(int k)
{
int p = last;
int np = newnode(s[p].maxl + 1);
for(;p && s[p].tr[k] == 0;p = s[p].par)s[p].tr[k] = np;
if(p == 0)s[np].par = root;
else
{
int q = s[p].tr[k];
if(s[p].maxl + 1 == s[q].maxl)s[np].par = q;
else
{
int nq = newnode(s[p].maxl + 1);
memcpy(s[nq].tr,s[q].tr,sizeof(s[q].tr));
s[nq].par = s[q].par;
s[q].par = s[np].par = nq;
for(;p && s[p].tr[k] == q;p = s[p].par)s[p].tr[k] = nq;
}
}
last = np;
return;
}
struct edge
{
int to,nxt;
}e[MAXN];
int edgenum = 0;
int lin[MAXN] = {0};
void add(int a,int b)
{
e[++edgenum] = (edge){b,lin[a]};lin[a] = edgenum;
return;
}
int ans[MAXN] = {0};
void dfs(int k)
{
for(int i = lin[k];i != 0;i = e[i].nxt)
{
dfs(e[i].to);
siz[k][0] += siz[e[i].to][0];
siz[k][1] += siz[e[i].to][1];
siz[k][2] += siz[e[i].to][2];
}
int v = 1ll * siz[k][0] * siz[k][1] % MOD * siz[k][2] % MOD;
ans[s[s[k].par].maxl + 1] = (ans[s[s[k].par].maxl + 1] + v) % MOD;
ans[s[k].maxl + 1] = (ans[s[k].maxl + 1] - v + MOD) % MOD;
return;
}
int main()
{
int l;int len = 0x3f3f3f3f;
scanf("%s",c + 1);l = strlen(c + 1);len = min(len,l);
last = root;for(int i = 1;i <= l;++i)extend(c[i] - 'a'),++siz[last][0];
scanf("%s",c + 1);l = strlen(c + 1);len = min(len,l);
last = root;for(int i = 1;i <= l;++i)extend(c[i] - 'a'),++siz[last][1];
scanf("%s",c + 1);l = strlen(c + 1);len = min(len,l);
last = root;for(int i = 1;i <= l;++i)extend(c[i] - 'a'),++siz[last][2];
for(int i = 2;i <= ptr;++i)add(s[i].par,i);
dfs(root);
for(int i = 1;i <= len;++i)
{
ans[i] = (ans[i] + ans[i - 1]) % MOD;
cout << ans[i] << " ";
}
cout << endl;
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡