bzoj 3238: [Ahoi2013]差异 (后缀自动机+树形dp)
2016-12-22 07:22
489 查看
3238: [Ahoi2013]差异
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2268 Solved: 1031
[Submit][Status][Discuss]
Description
![](http://www.lydsy.com/JudgeOnline/upload/201306/1(4).jpg)
Input
一行,一个字符串SOutput
一行,一个整数,表示所求值
Sample Input
cacaoSample Output
54HINT
2<=N<=500000,S由小写英文字母组成Source
[Submit][Status][Discuss]
题解:后缀自动机
这道题需要知道后缀自动机的一个性质,两个串的最长公共后缀,位于这两个串对应状态在parent树的最近公共祖先上。
分析一下题目中的式子,发现sigma len(Ti)+len(Tj)可以直接进行求解。关键是如何求解lcp ,因为上面的性质求得是最长公共后缀,所以我们将原串倒置,建立后缀自动机,得到的最长公共后缀就是原串的最长公共前缀。
知道这个后,问题就变成了,如何求解某个状态是多少对节点的后缀,这个可以用树形dp的思想,从下往上依次更新。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 1000003
#define LL long long
using namespace std;
int n,m,cnt,root,last,np,nq,p,q;
int ch
[30],fa
,l
,a
,v
,r
,pos
;
LL sum
;
char s
;
void extend(int x)
{
int c=a[x];
p=last; np=++cnt; last=np;
l[np]=x;
for (;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
if (!p) fa[np]=root;
else {
q=ch[p][c];
if (l[q]==l[p]+1) fa[np]=q;
else {
nq=++cnt; l[nq]=l[p]+1;
memcpy(ch[nq],ch[q],sizeof ch[nq]);
fa[nq]=fa[q];
fa[q]=fa[np]=nq;
for (;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
}
}
}
int main()
{
freopen("a.in","r",stdin);
freopen("my.out","w",stdout);
scanf("%s",s+1);
n=strlen(s+1);
last=root=++cnt;
for (int i=1;i<=n;i++) a[n-i+1]=s[i]-'a';
for (int i=1;i<=n;i++) extend(i);
for (int i=1;i<=cnt;i++) v[l[i]]++;
for (int i=1;i<=n;i++) v[i]+=v[i-1];
for (int i=1;i<=cnt;i++) pos[v[l[i]]--]=i;
p=1;
for (int i=1;i<=n;i++) {
p=ch[p][a[i]]; r[p]++; sum[p]++;
}
for (int i=cnt;i;i--){
int t=pos[i];
r[fa[t]]+=r[t];
}
/*for (int i=1;i<=cnt;i++) cout<<r[i]<<" ";
cout<<endl;
for (int i=1;i<=cnt;i++) cout<<l[i]<<" ";
cout<<endl;
for (int i=1;i<=cnt;i++) cout<<pos[i]<<" ";
cout<<endl;*/
LL ans=0;
for (int i=cnt;i>=1;i--){
int t=pos[i];
ans+=(LL)l[fa[t]]*(LL)r[t]*(LL)sum[fa[t]];
sum[fa[t]]+=(LL)r[t];
}
// cout<<ans<<endl;
printf("%I64d\n",(LL)(n+1)*(LL)n/2*(LL)(n-1)-2*ans);
}
相关文章推荐
- [BZOJ3238][Ahoi2013][后缀自动机][树形DP]差异
- [后缀自动机 构建后缀树 树形DP] BZOJ 3238 [Ahoi2013]差异
- [BZOJ3238][Ahoi2013]差异(后缀数组+单调栈||后缀自动机+树形dp)
- BZOJ 3238: [Ahoi2013]差异 后缀自动机 树形dp
- [后缀自动机][树形DP] BZOJ 3238: [Ahoi2013]差异
- BZOJ.3238.[AHOI2013]差异(后缀自动机 树形DP or 后缀数组 单调栈)
- bzoj3238 [Ahoi2013]差异 后缀自动机
- [BZOJ3238][Ahoi2013]差异(后缀自动机||后缀数组)
- BZOJ3238 Ahoi2013 差异 后缀自动机,后缀树,后缀数组解法三合一
- 【BZOJ3238】差异(AHOI2013)-后缀自动机+树形DP
- bzoj 3238: [Ahoi2013]差异 后缀自动机
- BZOJ 3238 [Ahoi2013]差异 ——后缀自动机
- BZOJ 3238 [Ahoi2013]差异 后缀自动机
- BZOJ_3238_[Ahoi2013]差异_后缀自动机
- [BZOJ3238] [AHOI2013] 差异 - 后缀自动机
- [Ahoi2013]差异 bzoj 3238 后缀自动机
- BZOJ 3238: [Ahoi2013]差异 [后缀自动机]
- BZOJ 3238 [Ahoi2013]差异(后缀自动机)
- [BZOJ3238][Ahoi2013]差异(后缀自动机)
- 【BZOJ 3238】[Ahoi2013]差异 后缀自动机构造后缀树