3238: [Ahoi2013]差异
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3660 Solved: 1655
[Submit][Status][Discuss]
Description
Input
一行,一个字符串S
Output
一行,一个整数,表示所求值
Sample Input
cacao
Sample Output
54
HINT
2<=N<=500000,S由小写英文字母组成
第一次写后缀自动机a~
把串翻过来 parent tree 就是后缀树了
之后就可以树形dp啦
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}
const int N=1000100;
int n;
struct SAM
{
int trans[N][26],par[N],mx[N];
int sz,root,suff;
int size[N];
ll ans;
SAM()
{
memset(mx,0,sizeof(mx));
memset(par,0,sizeof(par));
memset(trans,0,sizeof(trans));
sz=root=suff=1;ans=0;
}
void insert(int x)
{
int p=suff,np=++sz;
mx[np]=mx[p]+1;size[np]=1;
while(p && !trans[p][x])
trans[p][x]=np,p=par[p];
if(!p) par[np]=root;
else
{
int q=trans[p][x];
if(mx[q]==mx[p]+1) par[np]=q;
else
{
int nq=++sz;
mx[nq]=mx[p]+1;
memcpy(trans[nq],trans[q],sizeof(trans[q]));
par[nq]=par[q];
par[q]=par[np]=nq;
while(p && trans[p][x]==q)
trans[p][x]=nq,p=par[p];
}
}
suff=np;
}
void build(char *s)
{
register int i;
for(i=1;i<=n;++i) insert(s[i]-'a');
}
int last[N],ecnt;
struct EDGE{int to,nt;}e[N];
inline void add(int u,int v)
{e[++ecnt]=(EDGE){v,last[u]};last[u]=ecnt;}
void dp(int u)
{
for(int i=last[u],v;i;i=e[i].nt)
{
v=e[i].to;dp(v);
ans+=1ll*size[u]*size[v]*mx[u]<<1;
size[u]+=size[v];
}
}
void solve()
{
register int i;
for(i=2;i<=sz;++i) add(par[i],i);
dp(root);
ans=(1ll*n*(n+1)*(n-1)>>1)-ans;
}
}sam;
char s[N];
int main()
{
scanf("%s",s+1);
n=strlen(s+1);
reverse(s+1,s+1+n);
sam.build(s);
sam.solve();
cout<<sam.ans<<endl;
}
写的时候默写了一遍构造过程。。。
英语奇差 不要看 我就存下
/*
p->ST(T) np->ST(Tx)
Right(p)->{L} Right(np)->{L+1}
{p,v1,v2,v3...root} these ancestors of p
{r1,r2...rn} the Right of a v
if trans(vi,x) trans(vi+1,x) must be true
those v do not have trans(v,x) only rn can match x
so add a state from v to np
vp is the first one have had trans(v,x)
it's Right->{r1..rn}
q->trans(vp,x) so the Right of q is {(ri)+1 | without {(rn)+1} in because it's not update before}
we notice that we can't insert (rn)+1 straight
it may cause Max(q) get smaller
so only when Max(q)==Max(vp)+1 we can simply insert it
else we should create a new node named nq to express it and hold q
so
Max(nq)->Max(vp)+1
Parent(nq)=Parent(q)
Parent(q)=nq
Parent(np)=nq
Right(nq)=Right(q)+{L+1}
*/