JZOJ.5315【NOIP2017模拟8.19】小串串
字符串操作我们可以采用任何后缀的东西,包括后缀数组,后缀自动机,后缀树等等...
鉴于某蒟蒻只会后缀数组下面我们采用后缀数组的方法
本题要求出某字符子串在原串出现的次数,我们对原串求出height数组后,将height[i]值作为纵坐标,横坐标为i我们可以发现
矩形宽度即为某子串出现的次数,高度为该串的长度,每个单位高度的矩形就对答案贡献宽度的平方值,于是我们用单调栈来统计这矩形对答案的贡献,然后剩下的子串对答案都贡献1即可。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <algorithm> 6 #include <cmath> 7 #define N 100005 8 using namespace std; 9 long long t,n,sa[N],rank[N],tp[N],tax[N],h[N],len,a[N],top,id[N],sum,m,ans,oo[N]; 10 char qwq[N]; 11 void rsort(){ 12 for (int i=1;i<=m;i++) tax[i]=0; 13 for (int i=1;i<=len;i++) tax[rank[tp[i]]]++; 14 for (int i=1;i<=m;i++) tax[i]+=tax[i-1]; 15 for (int i=len;i>=1;i--) sa[tax[rank[tp[i]]]--]=tp[i]; 16 } 17 bool comp(long long *f,int x,int y,int w){ 18 return ((f[x]==f[y])&&(f[x+w]==f[y+w])); 19 } 20 void SS(){ 21 for (int i=1;i<=len;i++) rank[i]=a[i],tp[i]=i; 22 m=128;rsort(); 23 for (int i,p=1,w=1;p<len;w+=w,m=p){ 24 for (p=0,i=len-w+1;i<=len;i++) tp[++p]=i; 25 for (i=1;i<=len;i++) if (sa[i]>w) tp[++p]=sa[i]-w; 26 rsort();swap(tp,rank);rank[sa[1]]=1;p=1; 27 for (i=2;i<=len;i++) rank[sa[i]]=comp(tp,sa[i],sa[i-1],w)?p:++p; 28 } 29 int j=0,k=0; 30 for (int i=1;i<=len;oo[rank[i++]]=k) 31 for (k=k?k-1:k,j=sa[rank[i]-1];a[i+k]==a[j+k];k++); 32 } 33 void work(){ 34 long long tmp=0; 35 for (long long i=1;i<=len;i++){ 36 while ((h[id[top]]>=h[i])&&(top>0)){ 37 long long x=i-id[top-1]; 38 long long y=h[id[top]]-max(h[id[top-1]],h[i]); 39 ans+=x*x*y; 40 sum+=x*y; 41 top--; 42 } 43 id[++top]=i; 44 } 45 ans+=(n-sum); 46 printf("%lld\n",ans); 47 } 48 void clear(){ 49 memset(sa,0,sizeof(sa)); 50 memset(rank,0,sizeof(rank)); 51 memset(h,0,sizeof(h)); 52 memset(id,0,sizeof(id)); 53 memset(a,0,sizeof(a)); 54 top=0; 55 ans=0; 56 sum=0; 57 len=0; 58 n=0; 59 } 60 int main(){ 61 for (scanf("%lld",&t);t;t--){ 62 scanf("%s",qwq); 63 n=strlen(qwq); 64 for (int i=0;i<n;i++) 65 a[i+1]=(long long)qwq[i]-(long long)'a'+1; 66 len=n; 67 n=n*(n+1)/2; 68 SS(); 69 for (int i=1;i<=len;i++) 70 h[i]=oo[i+1]; 71 work(); 72 clear(); 73 } 74 return 0; 75 }
第一次打单调栈打到崩溃QAQ