bzoj3238 [Ahoi2013]差异 后缀数组+单调栈
【bzoj3238】[Ahoi2013]差异
Description
Input
一行,一个字符串S
Output
一行,一个整数,表示所求值
Sample Input
cacao
Sample Output
54
题解:
任意两个字符串的lcp是什么,就是如
a,b 那么若a==b 那么为len(a)
否则设sa[a]<sa[b] 那么为min(height[sa[a]+1-------sa[b]])
1 #include<cstring> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstdio> 6 7 #define N 500007 8 #define ll long long 9 using namespace std; 10 inline int read() 11 { 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();} 14 while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 18 int n; 19 int stk[N],f[N],g[N]; 20 struct SA 21 { 22 char s[N]; 23 int a[N],b[N],cnta[N],cntb[N],tsa[N],height[N],sa[N],rk[N*2]; 24 void Get_SA() 25 { 26 for (int i=0;i<=256;i++)cnta[i]=0; 27 for (int i=1;i<=n;i++)cnta[(int)s[i]]++; 28 for (int i=1;i<=256;i++)cnta[i]+=cnta[i-1]; 29 for (int i=n;i>=1;i--)sa[cnta[(int)s[i]]--]=i; 30 rk[sa[1]]=1; 31 for (int i=2;i<=n;i++)rk[sa[i]]=rk[sa[i-1]]+(s[sa[i]]!=s[sa[i-1]]); 32 for (int i=1;rk[sa[n]]!=n;i<<=1) 33 { 34 for (int j=1;j<=n;j++)a[j]=rk[j],b[j]=rk[j+i]; 35 for (int j=0;j<=n;j++)cnta[j]=cntb[j]=0; 36 for (int j=1;j<=n;j++)cnta[a[j]]++,cntb[b[j]]++; 37 for (int j=1;j<=n;j++)cnta[j]+=cnta[j-1],cntb[j]+=cntb[j-1]; 38 for (int j=n;j>=1;j--)tsa[cntb[b[j]]--]=j; 39 for (int j=n;j>=1;j--)sa[cnta[a[tsa[j]]]--]=tsa[j]; 40 rk[sa[1]]=1; 41 for (int j=2;j<=n;j++) 42 rk[sa[j]]=rk[sa[j-1]]+(a[sa[j]]!=a[sa[j-1]]||b[sa[j]]!=b[sa[j-1]]); 43 } 44 } 45 void Get_Height() 46 { 47 int len=0; 48 for (int i=1;i<=n;i++) 49 { 50 if (len)len--; 51 while(s[i+len]==s[sa[rk[i]-1]+len])len++; 52 height[rk[i]]=len; 53 } 54 } 55 }S; 56 int main() 57 { 58 scanf("%s",S.s+1); 59 n=strlen(S.s+1); 60 ll ans=0; 61 for (int i=1;i<=n;i++) 62 { 63 ans+=(ll)(i-1)*i; 64 ans+=(ll)i*(i-1)/2; 65 } 66 S.Get_SA(); 67 S.Get_Height(); 68 int tot=0; 69 for (int i=2;i<=n;i++) 70 { 71 while(tot>0&&S.height[i]<S.height[stk[tot]]) 72 f[stk[tot--]]=i-1; 73 stk[++tot]=i; 74 } 75 while(tot)f[stk[tot--]]=n; 76 tot=0; 77 for (int i=n;i>=2;i--) 78 { 79 while(tot>0&&S.height[i]<=S.height[stk[tot]])g[stk[tot--]]=i+1; 80 stk[++tot]=i; 81 } 82 while(tot)g[stk[tot--]]=2; 83 for (int i=2;i<=n;i++) 84 ans-=(ll)S.height[i]*(ll)(f[i]-i+1)*(ll)(i-g[i]+1)*2; 85 printf("%lld\n",ans); 86 }