# LOJ #6041. 「雅礼集训 2017 Day7」事情的相似度

LCP的长度是它们在parent树上的LCA（众所周知），所以我们考虑同时统计多个点之间的LCA对

CODE

#include<cstdio>
#include<cctype>
#include<vector>
#define RI register int
#define CI const int&
#define Tp template <typename T>
using namespace std;
const int N=100005;
int n,m,x,len[N<<1],anc[N<<1],id[N],ans[N],L[N],tot; vector <int> v[N];
class FileInputOutput
{
private:
static const int S=1<<21;
#define pc(ch) (Ftop<S?Fout[Ftop++]=ch:(fwrite(Fout,1,S,stdout),Fout[(Ftop=0)++]=ch))
char Fin[S],Fout[S],*A,*B; int Ftop,pt[15];
public:
{
x=0; char ch; while (!isdigit(ch=tc()));
while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
}
inline void get_digit(int& x)
{
char ch; while (!isdigit(ch=tc())); x=ch&15;
}
Tp inline void write(T x)
{
if (!x) return (void)(pc('0'),pc('\n')); RI ptop=0;
while (x) pt[++ptop]=x%10,x/=10; while (ptop) pc(pt[ptop--]+48); pc('\n');
}
inline void Fend(void)
{
fwrite(Fout,1,Ftop,stdout);
}
#undef tc
#undef pc
}F;
class Suffix_Automation
{
private:
int ch[N<<1][2],lst;
public:
inline Suffix_Automation() { lst=tot=1; }
inline void expand(CI c,CI pos)
{
int now=++tot,fa=lst; id[pos]=lst=now; len[now]=len[fa]+1;
while (fa&&!ch[fa][c]) ch[fa][c]=now,fa=anc[fa];
if (!fa) return (void)(anc[now]=1); int x=ch[fa][c];
if (len[fa]+1==len[x]) return (void)(anc[now]=x);
int y=++tot; ch[y][0]=ch[x][0]; ch[y][1]=ch[x][1];
anc[y]=anc[x]; len[y]=len[fa]+1; anc[now]=anc[x]=y;
while (fa&&ch[fa][c]==x) ch[fa][c]=y,fa=anc[fa];
}
}SAM;
class Tree_Array
{
private:
int mx[N];
inline void maxer(int& x,CI y)
{
if (y>x) x=y;
}
public:
#define lowbit(x) x&-x
{
for (;x;x-=lowbit(x)) maxer(mx[x],y);
}
inline int get(RI x,int ret=0)
{
for (;x<=n;x+=lowbit(x)) maxer(ret,mx[x]); return ret;
}
#undef lowbit
}BIT;
{
private:
struct splay
{
int ch[2],fa,val,tag;
}node[N<<1]; int stack[N<<1],top;
#define lc(x) node[x].ch[0]
#define rc(x) node[x].ch[1]
#define fa(x) node[x].fa
#define V(x) node[x].val
#define T(x) node[x].tag
inline void pushdown(CI now)
{
if (T(now)) T(lc(now))=V(lc(now))=T(rc(now))=V(rc(now))=T(now),T(now)=0;
}
inline int identify(CI now)
{
return rc(fa(now))==now;
}
inline void connect(CI x,CI y,CI d)
{
node[fa(x)=y].ch[d]=x;
}
inline bool isroot(CI now)
{
return lc(fa(now))!=now&&rc(fa(now))!=now;
}
inline void rotate(CI now)
{
int x=fa(now),y=fa(x),d=identify(now);
if (!isroot(x)) node[y].ch[identify(x)]=now; fa(now)=y;
connect(node[now].ch[d^1],x,d); connect(x,now,d^1);
}
inline void splay(int now)
{
int t=now; while (stack[++top]=t,!isroot(t)) t=fa(t);
while (top) pushdown(stack[top--]); for (;!isroot(now);rotate(now))
t=fa(now),!isroot(t)&&(rotate(identify(now)!=identify(t)?now:t),0);
}
public:
inline void init(void)
{
for (RI i=1;i<=tot;++i) fa(i)=anc[i];
}
inline void access(int x,CI pos,int y=0)
{
}
#undef lc
#undef rc
#undef fa
#undef V
#undef T
}LCT;
int main()
{
//freopen("A.in","r",stdin); freopen("A.out","w",stdout);