[Ahoi2013]差异 后缀自动机
2017-12-12 19:50
183 查看
[Ahoi2013]差异
输入格式
一行,一个字符串S
输出格式
一行,一个整数,表示所求值
样例输入
cacao
样例输出
54
数据规模
2<=N<=500000,S由小写英文字母组成
SAM求LCP的思路就是倒序建立自动机,把“后缀的前缀”转换为“前缀的后缀”。
两个状态表示的字符串最长公共后缀的长度就是两个状态在par树上的LCA的Max值。所以树形DP就好。
开了个Al,为了避免重复讨论。
#include<stdio.h> #include<cstring> #define ll long long #define MAXN 1000005 int N; char ch[MAXN]; ll Ans; int tot,las,rt,par[MAXN],Son[MAXN][26],Max[MAXN],Size[MAXN],Al[MAXN]; int push(int val) { Max[++tot]=val; return tot; } void Ins(char c) { int t=c-'a',p,q,np,nq; np=push(Max[las]+1);Size[np]=1;Al[np]=1; for(p=las;p&&(!Son[p][t]);p=par[p])Son[p][t]=np; if(!p)par[np]=rt; else { q=Son[p][t]; if(Max[q]==Max[p]+1)par[np]=q; else { nq=push(Max[p]+1); memcpy(Son[nq],Son[q],sizeof(Son[q])); par[nq]=par[q]; par[q]=par[np]=nq; for(;Son[p][t]==q;p=par[p])Son[p][t]=nq; } } las=np; } int T[MAXN],P[MAXN]; int main() { int i,t; scanf("%s",ch); N=strlen(ch); rt=las=push(0); for(i=N-1;i>=0;i--)Ins(ch[i]); Ans=1ll*(1ll*N+1ll)*1ll*N*(1ll*N-1ll)/2ll; for(i=1;i<=tot;i++)T[Max[i]]++; for(i=2;i<=N;i++)T[i]+=T[i-1]; for(i=tot;i;i--)P[T[Max[i]]--]=i; for(i=tot;i;i--)Size[par[P[i]]]+=Size[P[i]]; for(i=tot;i;i--) { t=P[i]; Ans-=2ll*Max[par[t]]*Size[t]*Al[par[t]]; Al[par[t]]+=Al[t]; } printf("%lld",Ans); }
相关文章推荐
- bzoj3238 [Ahoi2013]差异 后缀自动机
- bzoj 3238: [Ahoi2013]差异 后缀自动机
- [Ahoi2013]差异 bzoj 3238 后缀自动机
- BZOJ 3238: [Ahoi2013]差异 后缀自动机 树形dp
- BZOJ 3238 AHOI2013 差异 后缀自动机
- [后缀自动机 构建后缀树 树形DP] BZOJ 3238 [Ahoi2013]差异
- BZOJ3238 Ahoi2013 差异 后缀自动机,后缀树,后缀数组解法三合一
- 3238: [Ahoi2013]差异 后缀自动机
- 【BZOJ3238】【Ahoi2013】差异 后缀自动机
- bzoj 3238: [Ahoi2013]差异 (后缀自动机+树形dp)
- [bzoj3238][Ahoi2013]差异——后缀自动机
- BZOJ 3238 [Ahoi2013]差异 后缀自动机
- [后缀自动机][树形DP] BZOJ 3238: [Ahoi2013]差异
- [BZOJ3238][Ahoi2013]差异(后缀自动机)
- [BZOJ3238][Ahoi2013][后缀自动机][树形DP]差异
- BZOJ.3238.[AHOI2013]差异(后缀自动机 树形DP or 后缀数组 单调栈)
- [BZOJ3238][Ahoi2013]差异(后缀数组+单调栈||后缀自动机+树形dp)
- [BZOJ3238][Ahoi2013]差异(后缀自动机||后缀数组)
- BZOJ 3238: [Ahoi2013]差异 [后缀自动机]
- 字符串(后缀自动机):Ahoi2013 差异