[BZOJ4566][HAOI2016]找相同字符 后缀自动机
2017-12-26 18:44
435 查看
题目要求的就是B的每个字串在A中的出现次数之和。
我们考虑先建出A串的SAM,每个点所代表的串的个数就是|Righti|∗(Maxi−Maxfai)。我们可以发现经过一个点的时候,它在parent树上所有祖先代表的串出现次数也都加一,所以我们设Sumi为它和它祖先所代表串个数之和。
那么把B放在SAM上面跑,每经过一个点x,对答案的贡献为Sumfax+|Rightx|∗(dis−Maxfax),dis是B串走到当前节点可拓展的最长长度。
代码:
我们考虑先建出A串的SAM,每个点所代表的串的个数就是|Righti|∗(Maxi−Maxfai)。我们可以发现经过一个点的时候,它在parent树上所有祖先代表的串出现次数也都加一,所以我们设Sumi为它和它祖先所代表串个数之和。
那么把B放在SAM上面跑,每经过一个点x,对答案的贡献为Sumfax+|Rightx|∗(dis−Maxfax),dis是B串走到当前节点可拓展的最长长度。
代码:
#include<iostream> #include<cstdio> #include<cstring> #define ll long long using namespace std; const int maxn=400010; char s[maxn]; struct sam { int cnt,last,a[maxn][26],mx[maxn],fa[maxn],buc[maxn],ord[maxn]; ll ri[maxn],sum[maxn]; sam(){last=cnt=1;for(int i=0;i<=25;i++)a[0][i]=1;mx[0]=-1;} void extend(int c) { int p=last,np=last=++cnt;mx[np]=mx[p]+1;ri[np]=1; for(;p&&!a[p][c];p=fa[p]) a[p][c]=np; int q=a[p][c]; if(mx[q]==mx[p]+1) {fa[np]=q;return;} int nq=++cnt;mx[nq]=mx[p]+1; for(int ic=0;ic<26;ic++) a[nq][ic]=a[q][ic]; fa[nq]=fa[q]; fa[q]=fa[np]=nq; for(;p&&a[p][c]==q;p=fa[p]) a[p][c]=nq; } void pre() { for(int i=1;i<=cnt;i++) buc[mx[i]]++; for(int i=1;i<=cnt;i++) buc[i]+=buc[i-1]; for(int i=cnt;i;i--) ord[buc[mx[i]]--]=i; for(int i=cnt; 100f3 i;i--) ri[fa[ord[i]]]+=ri[ord[i]]; for(int i=2;i<=cnt;i++) sum[ord[i]]=sum[fa[ord[i]]]+ri[ord[i]]*(mx[ord[i]]-mx[fa[ord[i]]]); } ll run(int l) { ll re=0; for(int i=1,p=1,dis=0;i<=l;i++) { int c=s[i]-'a'; if(a[p][c]) dis++; else { while(p&&!a[p][c]) p=fa[p]; dis=mx[p]+1; } p=a[p][c]; re+=sum[fa[p]]+ri[p]*(dis-mx[fa[p]]); } return re; } }Tsam; int main() { scanf("%s",s+1); int len=strlen(s+1); for(int i=1;i<=len;i++) Tsam.extend(s[i]-'a'); Tsam.pre(); scanf("%s",s+1); printf("%lld",Tsam.run(strlen(s+1))); return 0; }
相关文章推荐
- bzoj 4566: [Haoi2016]找相同字符(后缀自动机)
- [后缀自动机 parent树] BZOJ 4566 [Haoi2016]找相同字符
- [Bzoj4566][Haoi2016]找相同字符(广义后缀自动机)
- 【bzoj4566】[Haoi2016]找相同字符【后缀自动机】
- BZOJ 4566: [Haoi2016]找相同字符 后缀自动机
- BZOJ_4566_[Haoi2016]找相同字符_后缀自动机
- [BZOJ4566][HAOI2016]找相同字符(后缀自动机)
- BZOJ 4566 [Haoi2016]找相同字符 ——广义后缀自动机
- BZOJ 4566: [Haoi2016]找相同字符 [后缀自动机]
- bzoj 4566: [Haoi2016]找相同字符 后缀自动机
- [BZOJ4566][Haoi2016]找相同字符(后缀自动机)
- [后缀自动机][树形DP] BZOJ 4566: [Haoi2016]找相同字符
- 4566: [Haoi2016]找相同字符 广义后缀自动机
- BZOJ 4566: [Haoi2016]找相同字符(后缀数组的两种做法)
- BZOJ4566 [Haoi2016]找相同字符 SAM+拓扑
- BZOJ 4566 [Haoi2016]找相同字符
- bzoj 4566: [Haoi2016]找相同字符【SAM上DP
- [BZOJ4566][HAOI2016]找相同字符
- 【BZOJ4566】[Haoi2016]找相同字符 后缀数组+单调栈
- BZOJ.4566.[HAOI2016]找相同字符(后缀自动机)