题目链接:
题意:若一个串t是A的子串且t不包含B,称t为A的合法子串。求A不同的合法子串的个数。
思路:首先求出B在A中出现的位置,t[i]表示从A串的i位置向后最早匹配完B的位置为t[i],注意是匹配完B。这样求出sa和height数组后,枚举i从1到n,设x=t[sa[i]]-sa[i],也就是sa[i]这个位置最多产生x个子串,再减去min(x,height[i])就是实际产生的子串。
int r[N],sa[N],wa[N],wb[N],wd[N],rank[N],h[N];int cmp(int *r,int a,int b,int len){ return r[a]==r[b]&&r[a+len]==r[b+len];}void da(int *r,int *sa,int n,int m){ int i,j,p,*x=wa,*y=wb,*t; FOR0(i,m) wd[i]=0; FOR0(i,n) wd[x[i]=r[i]]++; FOR1(i,m-1) wd[i]+=wd[i-1]; FORL0(i,n-1) sa[--wd[x[i]]]=i; for(j=1,p=1;p<<=1,m=p) { p=0; FOR(i,n-j,n-1) y[p++]=i; FOR0(i,n) if(sa[i]>=j) y[p++]=sa[i]-j; FOR0(i,m) wd[i]=0; FOR0(i,n) wd[x[i]]++; FOR1(i,m-1) wd[i]+=wd[i-1]; FORL0(i,n-1) sa[--wd[x[y[i]]]]=y[i]; t=x;x=y;y=t;p=1;x[sa[0]]=0; FOR1(i,n-1) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; }}void calHeight(int *r,int *sa,int n){ int i,j,k=0; FOR1(i,n) rank[sa[i]]=i; FOR0(i,n) { if(k) k--; j=sa[rank[i]-1]; while(i+k