傳送門php
咱們設詢問串爲\(t\)從頭開始的第一個字符串爲\(s[1]\),設在位置\(x\)匹配成功,則題目要求的就是\(\sum_{i=1}^xlcp(s[i],t)\)c++
能夠考慮先對\(s\)創建後綴自動機,而後考慮每個\(endpos\)類會對答案形成多少貢獻。spa
明顯能夠發現匹配位置以後的都對答案沒有貢獻,因此能夠使用線段樹合併維護\(right\)集合,查詢的時候直接查匹配位置前面的部分便可。code
#include <bits/stdc++.h> using namespace std; const int MAXN=2e5+7; #define mid ((l+r)>>1) int n,m,T[MAXN],st[MAXN<<5],L[MAXN<<5],R[MAXN<<5],sz; char s[MAXN]; inline void modify(int &u,int l,int r,int k) { if(!u) u=++sz; st[u]++; if(l==r) return; if(mid>=k) modify(L[u],l,mid,k); else modify(R[u],mid+1,r,k); } inline int query(int u,int l,int r,int dl,int dr) { if(dl<=l&&r<=dr) return st[u]; int ans=0; if(dl<=mid) ans+=query(L[u],l,mid,dl,dr); if(dr>mid) ans+=query(R[u],mid+1,r,dl,dr); return ans; } inline int merge(int u,int v) { if(!u||!v) return u+v; int rt=++sz; st[rt]=st[u]+st[v]; L[rt]=merge(L[u],L[v]);R[rt]=merge(R[u],R[v]); return rt; } struct SAM{ int trans[MAXN][27],maxlen[MAXN],fa[MAXN],od[MAXN],pos[MAXN],wt[MAXN]; int cnt,last,p,np,q,nq; SAM(){last=++cnt;} inline void insert(int x,int id){ p=last;last=np=++cnt;maxlen[np]=maxlen[p]+1;pos[np]=id; modify(T[np],1,n,id); while(!trans[p][x]&&p) trans[p][x]=np,p=fa[p]; if(!p) fa[np]=1; else { q=trans[p][x]; if(maxlen[q]==maxlen[p]+1) fa[np]=q; else { nq=++cnt;maxlen[nq]=maxlen[p]+1; pos[nq]=pos[q]; memcpy(trans[nq],trans[q],sizeof(trans[q])); fa[nq]=fa[q];fa[q]=fa[np]=nq; while(trans[p][x]==q) trans[p][x]=nq,p=fa[p]; } } } inline void get_right(){ for(int i=1;i<=cnt;i++) wt[maxlen[i]]++; for(int i=1;i<=n;i++) wt[i]+=wt[i-1]; for(int i=cnt;i;i--) od[wt[maxlen[i]]--]=i; for(int i=cnt;i>1;i--) T[fa[od[i]]]=merge(T[fa[od[i]]],T[od[i]]),pos[fa[od[i]]]=min(pos[fa[od[i]]],pos[od[i]]); } inline int check(){ int now=1; for(int i=1,l=strlen(s+1);i<=l;i++){ if(trans[now][s[i]-'0']) now=trans[now][s[i]-'0']; else return -1; } return pos[now]; } }sam; int main() { cin>>n; scanf("%s",s+1); for(int i=1;i<=n;i++) sam.insert(s[i]-'0',i); sam.get_right(); cin>>m; while(m--){ int ans=0; scanf("%s",s+1); int l=strlen(s+1),h=sam.check(); if(h==-1) ans=n; else ans=h+1-l; for(int i=1,now=1;i<l;i++){ if(sam.trans[now][s[i]-'0']) now=sam.trans[now][s[i]-'0']; else break; if(h==-1) ans+=query(T[now],1,n,1,n); else ans+=query(T[now],1,n,1,h-l+i); } printf("%d\n",ans); } }