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
| #include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair <int,int> Pii; #define reg register #define pb push_back #define mp make_pair #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) template <class T> inline void cmin(T &a,const T &b){ ((a>b)&&(a=b)); } template <class T> inline void cmax(T &a,const T &b){ ((a<b)&&(a=b)); }
const int N=1e5+10,M=3e6+10;
int n,m; char s[N],t[N];
int rk[N<<1],tmp[N],cnt[N],sa[N];
void Build(int n){ rep(i,1,n) cnt[int(s[i])]++; rep(i,1,200) cnt[i]+=cnt[i-1]; rep(i,1,n) rk[i]=cnt[(int)s[i]],sa[i]=i; for(reg int k=1;k<n;k<<=1) { for(reg int i=0;i<=n;++i) cnt[i]=0; for(reg int i=1;i<=n;++i) cnt[rk[i+k]]++; for(reg int i=1;i<=n;++i) cnt[i]+=cnt[i-1]; for(reg int i=n;i>=1;--i) tmp[cnt[rk[i+k]]--]=i;
for(reg int i=0;i<=n;++i) cnt[i]=0; for(reg int i=1;i<=n;++i) cnt[rk[i]]++; for(reg int i=1;i<=n;++i) cnt[i]+=cnt[i-1]; for(reg int i=n;i>=1;--i) sa[cnt[rk[tmp[i]]]--]=tmp[i];
for(reg int i=1;i<=n;++i) tmp[sa[i]]=tmp[sa[i-1]]+(rk[sa[i]]!=rk[sa[i-1]]||rk[sa[i]+k]!=rk[sa[i-1]+k]); for(reg int i=1;i<=n;++i) rk[i]=tmp[i]; } }
void FindChar(int &l,int &r,int len,int c){ int tl=l,tr=r; int lres=-1,rres=-1; while(l<=r){ int mid=(l+r)>>1; if(s[sa[mid]+len]<=c) l=mid+1,lres=mid; else r=mid-1; } if(lres==-1 || s[sa[lres]+len]!=c) { l=0; return; } l=tl,r=tr; while(l<=r){ int mid=(l+r)>>1; if(s[sa[mid]+len]>=c) r=mid-1,rres=mid; else l=mid+1; } l=rres,r=lres; }
ll ans[N]; int ql[M],qr[M],qid[M],qnxt[M]; int head[N],qc; int L[N],R[N];
struct BIT{ int s[N]; void Add(int p) { while(p<=n) s[p]++,p+=p&-p; } int Que(int p) { int res=0; while(p) res+=s[p],p-=p&-p; return res; } int Que(int l,int r){ return Que(r)-Que(l-1); } } T; struct Tree{ int s[N<<2]; void Build(int p,int l,int r){ if(l==r) { s[p]=sa[l]; return ;} int mid=(l+r)>>1; Build(p<<1,l,mid),Build(p<<1|1,mid+1,r); s[p]=min(s[p<<1],s[p<<1|1]); } int Que(int p,int l,int r,int ql,int qr){ if(ql<=l && r<=qr) return s[p]; int mid=(l+r)>>1,res=1e9; if(ql<=mid) cmin(res,Que(p<<1,l,mid,ql,qr)); if(qr>mid) cmin(res,Que(p<<1|1,mid+1,r,ql,qr)); return res; } }SGT;
int main(){ scanf("%d%s",&n,s+1); Build(n),scanf("%d",&m); SGT.Build(1,1,n); rep(i,1,m) { scanf("%s",t+1); L[0]=1,R[0]=n; int len=0,pos=1; for(int j=1;t[j];++j) { L[len=j]=L[j-1],R[j]=R[j-1]; FindChar(L[j],R[j],j-1,t[j]); if(!L[j]){ pos=0; break; } ans[i]+=R[j]-L[j]+1; } if(pos && (pos=SGT.Que(1,1,n,L[len],R[len]))<n) { ans[i]+=pos-1,pos++; rep(j,1,len){ qc++,ql[qc]=L[j],qr[qc]=R[j],qid[qc]=i,qnxt[qc]=head[pos]; head[pos]=qc; } } else ans[i]+=n; } drep(i,n,1){ T.Add(rk[i]); for(int j=head[i];j;j=qnxt[j]) ans[qid[j]]-=T.Que(ql[j],qr[j]); } rep(i,1,m) printf("%lld\n",ans[i]); }
|