1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
| #include<bits/stdc++.h> using namespace std; typedef long long ll; #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i) #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
char IO; template <class T=int> T rd(){ T s=0; int f=0; while(!isdigit(IO=getchar())) f|=IO=='-'; do s=(s<<1)+(s<<3)+(IO^'0'); while(isdigit(IO=getchar())); return f?-s:s; }
enum{N=100010}; int n,m; char s[N]; struct Suffix_Array{ int rk[N<<1],tmp[N],cnt[N],sa[N],lcp[N]; void Build() { rep(i,1,n) cnt[s[i]-'a']++; rep(i,1,25) cnt[i]+=cnt[i-1]; rep(i,1,n) rk[i]=cnt[s[i]-'a']; drep(i,n,1) sa[cnt[s[i]-'a']--]=i; for(int m=n,k=1;;k<<=1) { int h=0; rep(i,n-k+1,n) tmp[++h]=i; rep(i,1,n) if(sa[i]>k) tmp[++h]=sa[i]-k; rep(i,1,n) cnt[rk[sa[i]]]=i; drep(i,n,1) sa[cnt[rk[tmp[i]]]--]=tmp[i]; rep(i,1,n) tmp[sa[i]]=tmp[sa[i-1]]+(rk[sa[i]]!=rk[sa[i-1]]||rk[sa[i-1]+k]!=rk[sa[i]+k]); rep(i,1,n) rk[i]=tmp[i]; if((m=rk[sa[n]])==n) break; } int h=0; rep(i,1,n) { int j=sa[rk[i]-1]; if(h) h--; while(s[i+h]==s[j+h]) h++; lcp[rk[i]-1]=h; } } } ;
struct LCPer:Suffix_Array{ int st[20][N],Log[N]; void Init() { rep(i,2,n) Log[i]=Log[i>>1]+1; rep(i,1,n) st[0][i]=lcp[i]; rep(i,1,Log[n]) { int len=1<<(i-1); rep(j,1,n-len+1) st[i][j]=min(st[i-1][j],st[i-1][j+len]); } } int LCP(int i,int j) { if(i==j) return n-sa[i]+1; if(i>j) swap(i,j); j--; int d=Log[j-i+1]; return min(st[d][i],st[d][j-(1<<d)+1]); } } S;
struct SA_Solver:Suffix_Array{ int stk[N],top,ls[N],rs[N],mk[N]; ll ans,F[N*2]; set <int> st[N*2]; void dfs(int &u,int l,int r,int lst){ if(l==r) { u=++m; int p=sa[l]; if(p>2) { int q=n-(p-2)+1; F[u]=n-q+1; st[u].insert(S.rk[q]); } if(p>1) ans+=1ll*(n-p+1-lst)*(F[u]+1); return; } dfs(ls[u],l,u,lcp[u]),dfs(rs[u],u+1,r,lcp[u]); if(st[ls[u]].size()>st[rs[u]].size()) swap(ls[u],rs[u]); swap(st[u],st[rs[u]]),F[u]=F[ls[u]]+F[rs[u]];
int t=-1; for(int i:st[ls[u]]) { if(~t) F[u]+=S.LCP(t,i); t=i; auto r=st[u].upper_bound(i); if(r!=st[u].end()) F[u]-=S.LCP(i,*r); if(r!=st[u].begin()) { auto l=r; l--; if(r!=st[u].end()) F[u]+=S.LCP(*l,*r); F[u]-=S.LCP(*l,i); } st[u].insert(i); } ans+=1ll*(lcp[u]-lst)*(F[u]+1); } void Solve(){ rep(i,1,n-1) { while(top && lcp[stk[top]]>lcp[i]) ls[i]=stk[top--]; if(top) rs[stk[top]]=i; stk[++top]=i; } rep(i,1,n-1) mk[ls[i]]=mk[rs[i]]=1;
rep(i,1,n) ans+=n-i+1-lcp[i]; ans++; int lst=-1; rep(i,1,n) if(S.sa[i]>1) { ans+=n-S.sa[i]+1; if(~lst) ans-=min(S.LCP(i,lst),min(n-S.sa[i]+1,n-S.sa[lst]+1)); lst=i; } ans++; rep(i,1,n-1) if(!mk[i]) dfs(i,1,n,0); printf("%lld\n",ans); } } T;
int main(){ scanf("%s",s+1),n=m=strlen(s+1); if(n==1) return puts("3"),0; T.Build(),reverse(s+1,s+n+1),S.Build(),S.Init(); T.Solve(); }
|