Time Limit: 20 Sec
Memory Limit: 512 MB
Description
Input
一行,一个字符串S
Output
一行,一个整数,表示所求值
Sample Input
cacao
Sample Output
54
HINT
2 < = N < = 500000 2<=N<=500000 2<=N<=500000 , S由小写英文字母组成
题解:
学了一发后缀数组,
s
a
[
i
]
=
j
sa[i] = j
sa[i]=j表示为按照从小到大排名为i的后缀 是以j(下标)开头的后缀
r
k
[
i
]
=
j
rk[i] = j
rk[i]=j表示为按照从小到大排名 以i为下标开始的后缀 排名为
j
j
j
h
[
i
]
h[i]
h[i]表示
l
c
p
(
i
,
i
−
1
)
lcp(i,i-1)
lcp(i,i−1)
用单调栈维护
l
c
p
(
L
,
R
)
=
h
[
i
]
lcp(L,R)=h[i]
lcp(L,R)=h[i]重复计数就取左不取右。
#include<bits/stdc++.h>
#define LiangJiaJun main
#define ll long long
#define pa pair<int,int>
#define INF 1000000000
using namespace std;
ll ans;
int l,k,p,q,a[500004],v[500004];
int sa[2][500004],rk[2][500004],h[500004];
char str[500004];
int st[500004],L[500004],R[500004],top;
void work(int *sa,int *rk,int *SA,int *RK){
for(int i=1;i<=l;i++)v[rk[sa[i]]]=i;
for(int i=l;i;i--){
if(sa[i]>k){
SA[v[rk[sa[i]-k]]--]=sa[i]-k;
}
}
for(int i=l-k+1;i<=l;i++)SA[v[rk[i]]--]=i;
for(int i=1;i<=l;i++){
RK[SA[i]]=RK[SA[i-1]]+(rk[SA[i-1]]!=rk[SA[i]]||rk[SA[i-1]+k]!=rk[SA[i]+k]);
}
return ;
}
void presa(){
for(int i=1;i<=l;i++)v[a[i]]++;
for(int i=1;i<=30;i++)v[i]+=v[i-1];
for(int i=1;i<=l;i++)sa[p][v[a[i]]--]=i;
for(int i=1;i<=l;i++){
rk[p][sa[p][i]]=rk[p][sa[p][i-1]]+(a[sa[p][i]]!=a[sa[p][i-1]]);
}
for(k=1;k<l;k<<=1,swap(p,q))work(sa[p],rk[p],sa[q],rk[q]);
for(int k=0,i=1;i<=l;i++){
int j=sa[p][rk[p][i]-1];
while(str[j+k]==str[i+k])k++;
h[rk[p][i]]=k;
if(k>0)k--;
}
}
void solve(){
h[0]=-INF;
for(int i=1;i<=l;i++)ans+=1LL*i*(l-1);
top=0;st[0]=0;
for(int i=1;i<=l;i++){
while(h[i]<=h[st[top]])top--;
if(st[top]==0)L[i]=1;
else L[i]=st[top]+1;
st[++top]=i;
}
h[l+1]=-INF;top=0;st[0]=l+1;
for(int i=l;i;i--){
while(h[i]<h[st[top]])top--;
if(st[top]==l+1)R[i]=l;
else R[i]=st[top]-1;
st[++top]=i;
}
for(int i=1;i<=l;i++){
ans-=2LL*(i-L[i]+1)*(R[i]-i+1)*h[i];
}
}
int w33ha(){
memset(v,0,sizeof(v));
memset(h,0,sizeof(h));
memset(sa,0,sizeof(sa));
memset(rk,0,sizeof(rk));
ans=0;p=0;q=1;
l=strlen(str+1);
for(int i=1;i<=l;i++)a[i]=str[i]-'a'+1;
presa();
solve();
printf("%lld\n",ans);
return 0;
}
int LiangJiaJun(){
while(scanf("%s",str+1)!=EOF)w33ha();
return 0;
}