5769 Substring
题目大意:给一字符和一字符串,求包含这字符的连续子串的个数。
题解:处理出后缀数组中的sa[]数组和height[]数组。在不考虑包含字符X的情况下,不同子串的个数为sum+=length−(sa[i]+height[i]);(i:1->n)1lengthlength−(sa[i]+height[i])
如果要求字符X,只需要记录距离sa[i]最近的字符X的位置(用nxt[sa[i]]表示)即可,个数为sum+=length−max(nxt[sa[i]],sa[i]+height[i]);(i:1->n)11lengthlength−max(nxt[sa[i]],sa[i]+height[i])
# include<stdio.h> # include<algorithm> # include<iostream> # include<string.h> using namespace std; # define N 210 const int inf=0x3f3f3f3f; const int maxn=(int)1e7+88; int t1[maxn],t2[maxn],c[maxn]; bool cmp(int *r,int a,int b,int l) { return r[a]==r[b]&&r[a+l]==r[b+l]; } void da(int str[],int sa[],int dddd[],int height[],int n,int m) { n++; int i,j,p,*x=t1,*y=t2; for(int i=0; i<m; i++)c[i]=0; for(int i=0; i<n; i++)c[x[i]=str[i]]++; for(int i=1; i<m; i++)c[i]+=c[i-1]; for(int i=n-1; i>=0; i--)sa[--c[x[i]]]=i; for(int j=1; j<=n; j<<=1) { p=0; for(int i=n-j; i<n; i++) y[p++]=i; for(int i=0; i<n; i++)if(sa[i]>=j)y[p++]=sa[i]-j; for(int i=0; i<m; i++)c[i]=0; for(int i=0; i<n; i++)c[x[y[i]]]++; for(int i=1; i<m; i++)c[i]+=c[i-1]; for(int i=n-1; i>=0; i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1; x[sa[0]]=0; for(int i=1; i<n; i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; if(p>=n)break; m=p; } int k=0; n--; for(int i=0; i<=n; i++)dddd[sa[i]]=i; for(int i=0; i<n; i++) { if(k)k--; j=sa[dddd[i]-1]; while(str[i+k]==str[j+k])k++; height[dddd[i]]=k; } } int dddd[maxn],height[maxn]; int rmq[maxn]; int mm[maxn]; int best[20][maxn]; void initrmq(int n) { mm[0]=-1; for(int i=1; i<=n; i++) mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1]; for(int i=1; i<=n; i++)best[0][i]=i; for(int i=1; i<=mm[n]; i++) for(int j=1; j+(1<<i)-1<=n; j++) { int a=best[i-1][j]; int b=best[i-1][j+(1<<(i-1))]; if(rmq[a]<rmq[b])best[i][j]=a; else best[i][j]=b; } } //楼上后缀数组的板子;char str[maxn]; int r[maxn]; int sa[maxn]; int nes[maxn]; int main() { // freopen("1006.txt", "r", stdin); // freopen("out.txt", "w", stdout); char x; int t; int tt=0; scanf("%d",&t); while(t--) { scanf(" %c%s",&x,str); int n=strlen(str); for(int i=0; i<n; i++) r[i]=str[i]; r[n]=0; da(r,sa,dddd,height,n,300); int q=n;//考虑没有字符x的时候就没有字符; for(int i=n-1; i>=0; i--) { if(x==str[i]) { q=i; nes[i]=q; } else { nes[i]=q; } } height[1]=0; long long ans=0; for(int i=1; i<=n; i++) { if(ans<0)printf("."); ans+=(n-max(nes[sa[i]],sa[i]+height[i])); } printf("Case #%d: %I64d\n",++tt,ans); } return 0; }


浙公网安备 33010602011771号