您的位置:首页 > 其它

bzoj3238 [Ahoi2013]差异

2017-10-06 13:36 253 查看

Description



Input

一行,一个字符串S

Output

一行,一个整数,表示所求值

Sample Input

cacao

Sample Output

54

HINT

2<=N<=500000,S由小写英文字母组成

正解:后缀自动机+后缀树。

这题就是用后缀自动机构造后缀树,然后就很简单了。

有一个性质,反串的后缀自动机构成的$parent$树就是后缀树。

然后我们构造出后缀树以后,就可以直接树形$dp$求出答案了。

另外注意,后缀自动机中新建的结点是不能算进方案中的,因为它并不是后缀结点。

#include <bits/stdc++.h>
#define il inline
#define RG register
#define ll long long
#define N (1000010)

using namespace std;

struct edge{ int nt,to; }g
;

int ch
[26],head
,fa
,sz
,l
,la,tot,len,num;
char s
;
ll ans;

il int gi(){
RG int x=0,q=1; RG char ch=getchar();
while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
if (ch=='-') q=-1,ch=getchar();
while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
return q*x;
}

il void insert(RG int from,RG int to){
g[++num]=(edge){head[from],to},head[from]=num; return;
}

il void add(RG int c){
RG int p=la,np=++tot; la=np,l[np]=l[p]+1,sz[np]=1;
for (;p && !ch[p][c];p=fa[p]) ch[p][c]=np;
if (!p){ fa[np]=1; return; } RG int q=ch[p][c];
if (l[q]==l[p]+1) fa[np]=q; else{
RG int nq=++tot; l[nq]=l[p]+1;
fa[nq]=fa[q],fa[q]=fa[np]=nq;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
for (;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
}
return;
}

il void dfs(RG int x){
for (RG int i=head[x],v;i;i=g[i].nt){
v=g[i].to,dfs(g[i].to);
ans+=1LL*sz[x]*sz[v]*l[x],sz[x]+=sz[v];
}
return;
}

int main(){
#ifndef ONLINE_JUDGE
freopen("difference.in","r",stdin);
freopen("difference.out","w",stdout);
#endif
scanf("%s",s+1),len=strlen(s+1),tot=la=1;
for (RG int i=len;i;--i) add(s[i]-'a');
for (RG int i=2;i<=tot;++i) insert(fa[i],i);
dfs(1),cout<<1LL*(len-1)*len*(len+1)/2-2*ans; return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: