BZOJ 3238 差异(后缀自动机+树上统计)
2018-03-22 08:46
183 查看
3238: [Ahoi2013]差异
Time Limit:20 Sec Memory Limit:
512 MB
Submit:
4179 Solved:
1896
[Submit][Status][Discuss]
Description
Input
一行,一个字符串S
Output
一行,一个整数,表示所求值
Sample Input
cacao
Sample Output
54
HINT
2<=N<=500000,S由小写英文字母组成中文题,题意自己看看吧。
看到表达式,难求的主要是lcp,任意两个后缀的lcp。即使用上后缀数组求这么多个lcp也是要超时的。但是这里如果用后缀自动机的性质,会好很多。
我们之前在介绍后缀自动机的时候说过,parent树表示父亲是儿子最长的一个后缀。那么,对于最长公共后缀的时候,两个字符串对应状态的LCA的len值,就是我们最长公共后缀的长度。即两个字符串往上走,都是走到他们的后缀,然后越往上长度越短,所以说第一个相同后缀一定是最长的,对应长度就是LCA的len。对于本题的lcp,同样的道理,只需要我们再加入字符串的时候反过来倒着建立后缀自动机即可。
建立完自动机之后,要考虑如何求和,因为直接枚举求还是会超时的。经典的套路,我们考虑每一个点作为LCA的总贡献。单个贡献显然就是那个点的len值,要求的就是该点作为LCA的次数。这个次数又是一个树上统计的经典问题,类似树形dp的方式,求该点每一个子树中有效点的累积乘积和即可。这里的有效点指不考虑后缀自动机中拆点操作时的点。
至于表达式中前面两项,求个和可以得出前两项的和为(n-1)*n*(n+1)/2。用该答案减去lcp之和的两倍即可。具体见代码:
#include<bits/stdc++.h> #define LL long long #define N 500010 using namespace std; struct Suffix_Automation { int tot,cur; struct node{int ch[26],len,fa,r;} T[N<<1]; void init(){cur=tot=1;memset(T,0,sizeof(T));} void ins(int x,int id) { int p=cur; cur=++tot; T[cur].len=id; T[cur].r++; //标记为有效点 for(;p&&!T[p].ch[x];p=T[p].fa) T[p].ch[x]=cur; if (!p) {T[cur].fa=1;return;}int q=T[p].ch[x]; if (T[p].len+1==T[q].len) {T[cur].fa=q;return;} int np=++tot; memcpy(T[np].ch,T[q].ch,sizeof(T[q].ch)); T[np].fa=T[q].fa; T[q].fa=T[cur].fa=np; T[np].len=T[p].len+1; for(;p&&T[p].ch[x]==q;p=T[p].fa) T[p].ch[x]=np; } } SAM; vector<int> g[N<<1]; LL ans; char s ; void dfs(int x) //类似树形dp求每个点的总贡献 { for(int i=0;i<g[x].size();i++) { int y=g[x][i]; dfs(y); ans-=(LL)SAM.T[x].r*SAM.T[y].r*SAM.T[x].len*2; //有效点个数的乘积和 SAM.T[x].r+=SAM.T[y].r; //累积起来 } } int main() { SAM.init(); scanf("%s",s); LL n=strlen(s); for(int i=n-1;i>=0;i--) SAM.ins(s[i]-'a',n-i); for(int i=2;i<=SAM.tot;i++) g[SAM.T[i].fa].push_back(i); ans=n*(n-1)*(n+1)/2; dfs(1); printf("%lld\n",ans); }
相关文章推荐
- [bzoj3238][Ahoi2013]差异——后缀自动机
- [BZOJ3238][Ahoi2013][后缀自动机][树形DP]差异
- bzoj3238 [Ahoi2013]差异 后缀自动机
- bzoj 3238: [Ahoi2013]差异 后缀自动机
- [BZOJ3238][Ahoi2013]差异(后缀自动机)
- BZOJ 3238: [Ahoi2013]差异 后缀自动机 树形dp
- BZOJ3238 Ahoi2013 差异 后缀自动机,后缀树,后缀数组解法三合一
- [BZOJ3238] [AHOI2013] 差异 - 后缀自动机
- BZOJ 3238 [Ahoi2013]差异 ——后缀自动机
- BZOJ 3238 [Ahoi2013]差异 后缀自动机
- BZOJ3238: [Ahoi2013]差异 (后缀自动机)
- [后缀自动机][树形DP] BZOJ 3238: [Ahoi2013]差异
- bzoj 3238: [Ahoi2013]差异 (后缀自动机+树形dp)
- BZOJ 3238 差异 [后缀自动机]
- [BZOJ3238][Ahoi2013]差异(后缀自动机||后缀数组)
- [Ahoi2013]差异 bzoj 3238 后缀自动机
- 【BZOJ3238】差异(AHOI2013)-后缀自动机+树形DP
- 【bzoj3238】差异 后缀自动机
- BZOJ 3238 [Ahoi2013]差异(后缀自动机)
- [BZOJ3238][Ahoi2013]差异(后缀数组+单调栈||后缀自动机+树形dp)