[AHOI2013]差异
2018-02-26 17:35
127 查看
题目描述
给定一个长度为 $n$ 的字符串 $S$ ,令 $T_i$ 表示它从第 $i$ 个字符开始的后缀。求$\displaystyle \sum_{1\leqslant i<j\leqslant n}\text{len}(T_i)+\text{len}(T_j)-2\times\text{lcp}(T_i,T_j)$
其中,$\text{len}(a)$ 表示字符串 $a$ 的长度,$\text{lcp}(a,b)$ 表示字符串 $a$ 和字符串 $b$ 的最长公共前缀。
输入输出格式
输入格式:一行,一个字符串 $S$ 。
输出格式:
一行,一个整数,表示所求值。
输入输出样例
输入样例#1:复制
cacao
输出样例#1: 复制
54
说明
对于 100% 的数据,保证 $2\leqslant n\leqslant 500000$ ,且均为小写字母。先用后缀数组求出height数组(h数组)
那么两个点i,j的LCP就是$min{h[k] | i+1<=k<=j}$
考虑每个h[i]的贡献
假设L[i]表示L[i]~i-1的h值都大于等于h[i]
而R[i]表示i+1~R[i]的h值大于h[i](之所以不是大于等于是为了避免相同的h带来重复答案)
$ans-=2*lcp(T_i,T_j)$
$ans-=2*(i-L[i]+1)*(R[i]-i+1)*h[i]$
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; typedef long long lol; int n,m,c[600001]; int x[600001],y[600001],SA[600001],s[600001],rank[600001],st[600001],top; lol L[600001],R[600001]; lol h[600001],ans,sum; char ch[600001]; void radix_sort() {int i; for (i=0;i<m;i++) c[i]=0; for (i=0;i<n;i++) c[x[y[i]]]++; for (i=1;i<m;i++) c[i]+=c[i-1]; for (i=n-1;i>=0;i--) SA[--c[x[y[i]]]]=y[i]; } void build() {int i,j,k,p; for (i=0;i<n;i++) y[i]=i,x[i]=s[i]; m=500000; radix_sort(); for (k=1;k<=n;k*=2) { p=0; for (i=n-k;i<n;i++) y[p++]=i; for (i=0;i<n;i++) if (SA[i]>=k) y[p++]=SA[i]-k; radix_sort(); p=1;swap(x,y); x[SA[0]]=0; for (i=1;i<n;i++) x[SA[i]]=((y[SA[i]]==y[SA[i-1]])&&((SA[i]+k<n?y[SA[i]+k]:-1)==(SA[i-1]+k<n?y[SA[i-1]+k]:-1)))?p-1:p++; if (p>n) break; m=p; } for (i=0;i<n;i++) rank[SA[i]]=i; int len=0; for (i=0;i<n;i++) if(rank[i]>0) { if (len) len--; j=SA[rank[i]-1]; while (i+len<n&&j+len<n&&(s[i+len]==s[j+len])) len++; h[rank[i]]=len; } } int main() {int i,j; cin>>ch; n=strlen(ch); for (i=0;i<n;i++) { s[i]=ch[i]-'a'+1; } build(); for (i=0;i<n;i++) { while (top&&h[i]<=h[st[top]]) top--; if (top==0) L[i]=0; else L[i]=st[top]+1; st[++top]=i; } top=0; for (i=n-1;i>=0;i--) { while (top&&h[i]<h[st[top]]) top--; if (top==0) R[i]=n-1; else R[i]=st[top]-1; st[++top]=i; } for (i=1;i<=n;i++) ans+=(lol)i*(lol)(n-1); for (i=0;i<n;i++) { ans-=2ll*((lol)i-(lol)L[i]+1ll)*((lol)R[i]-(lol)i+1ll)*(lol)h[i]; } printf("%lld\n",ans); }
相关文章推荐
- [Ahoi2013]差异 后缀自动机
- [BZOJ3238][AHOI2013]差异(SAM)
- BZOJ3238 [Ahoi2013]差异 【后缀数组 + 单调栈】
- BZOJ.3238.[AHOI2013]差异(后缀自动机 树形DP or 后缀数组 单调栈)
- 【bzoj3238】[Ahoi2013]差异 后缀数组+单调栈
- 后缀数组+单调栈 【Ahoi2013】bzoj3238 差异
- bzoj3238 [Ahoi2013]差异
- [BZOJ3238][Ahoi2013]差异解题报告|后缀数组
- [BZOJ3238][Ahoi2013]差异
- [后缀自动机][树形DP] BZOJ 3238: [Ahoi2013]差异
- BZOJ 3238 [Ahoi2013]差异 后缀数组+单调栈
- 【AHOI2013】bzoj3238 差异
- bzoj 3238: [Ahoi2013]差异 -- 后缀数组
- BZOJ 3238 [Ahoi2013]差异
- bzoj3238 [Ahoi2013]差异
- 【bzoj3238】[Ahoi2013]差异
- [BZOJ3238][AHOI2013]差异(后缀数组)
- BZOJ3238: [Ahoi2013]差异
- [BZOJ3238][Ahoi2013][后缀自动机][树形DP]差异
- BZOJ 3238: [Ahoi2013]差异 [后缀自动机]