先考虑l=1,r=|s|的部分分,需要求出t每一个前缀的不是s子串的最长后缀,记作pp[k],有以下限制:
1.pp[pos[k]]<len(pos[k]表示k的某一个结束位置),因为不能被匹配
1.pp[pos[k]]<len(pos[k]表示k的某一个结束位置),因为不能被匹配
2.len[fa[k]]<len<=len[k],因为这个点上本来就只有这些串
由此得到答案为sigma(max(0,len[j]-max(len[fa[j]],pp[pos[j]])))(要对0取max)
维护出s从li到ri的后缀自动机,但好像不太容易。不妨换个角度,即要求其的right集合存在一个值在[li,ri]之间
也就是说在计算s的SAM同时,求出每一个节点的right集合
维护线段树,线段树下标表示位置,值表示是否是right集合。那么SAM上的父亲就是所有儿子right集合的并,也就是线段树合并
(注意:因为要保留参与合并的线段树,所以要新建节点)
同时线段树还能很方便的判断区间中有没有1,求区间和即可
但是要注意,此时不能直接跳fa,而是要一个一个减长度(因为可能无法匹配该节点最长串,但能匹配较短的串)
View Code
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 2000005 4 #define mid (l+r>>1) 5 struct ji{ 6 int nex,to; 7 }edge[N]; 8 int V,x,last,fa[N],pos[N],len[N],ch[N][26]; 9 int VV,E,n,m,a,b,r[N],head[N],pp[N],ls[N*16],rs[N*16]; 10 long long ans; 11 char s[N],t[N]; 12 int New(){ 13 fa[++V]=0; 14 len[V]=pos[V]=0; 15 memset(ch[V],0,sizeof(ch[V])); 16 return V; 17 } 18 void add_edge(int x,int y){ 19 edge[E].nex=head[x]; 20 edge[E].to=y; 21 head[x]=E++; 22 } 23 void add(int c,int id){ 24 int p=last,np=last=New(); 25 len[np]=len[p]+1; 26 pos[V]=id; 27 for(;(p)&&(!ch[p][c]);p=fa[p])ch[p][c]=np; 28 if (!p)fa[np]=x; 29 else{ 30 int q=ch[p][c]; 31 if (len[q]==len[p]+1)fa[np]=q; 32 else{ 33 int nq=New(); 34 pos[nq]=pos[q]; 35 len[nq]=len[p]+1; 36 memcpy(ch[nq],ch[q],sizeof(ch[q])); 37 fa[nq]=fa[q]; 38 fa[q]=fa[np]=nq; 39 for(;(p)&&(ch[p][c]==q);p=fa[p])ch[p][c]=nq; 40 } 41 } 42 } 43 void update(int &k,int l,int r,int x){ 44 k=++VV; 45 if (l==r)return; 46 if (x<=mid)update(ls[k],l,mid,x); 47 else update(rs[k],mid+1,r,x); 48 } 49 int query(int k,int l,int r,int x,int y){ 50 if ((!k)||(l>y)||(x>r))return 0; 51 if ((x<=l)&&(r<=y))return 1; 52 return query(ls[k],l,mid,x,y)|query(rs[k],mid+1,r,x,y); 53 } 54 void merge(int &k1,int k2){ 55 if (k1*k2==0){ 56 k1+=k2; 57 return; 58 } 59 ls[++VV]=ls[k1]; 60 rs[VV]=rs[k1]; 61 k1=VV; 62 merge(ls[k1],ls[k2]); 63 merge(rs[k1],rs[k2]); 64 } 65 void dfs(int k){ 66 if (pos[k])update(r[k],1,n,pos[k]); 67 for(int i=head[k];i!=-1;i=edge[i].nex){ 68 dfs(edge[i].to); 69 merge(r[k],r[edge[i].to]); 70 } 71 } 72 int main(){ 73 scanf("%s%d",s,&m); 74 len[0]=-1; 75 n=strlen(s); 76 x=last=New(); 77 for(int i=0;s[i];i++)add(s[i]-'a',i+1); 78 memset(head,-1,sizeof(head)); 79 for(int i=2;i<=V;i++)add_edge(fa[i],i); 80 dfs(1); 81 x=New(); 82 for(int i=1;i<=m;i++){ 83 scanf("%s%d%d",t,&a,&b); 84 V=x-1; 85 last=New(); 86 for(int j=0,k=1,l=0;t[j];pp[j++]=++l){ 87 int c=t[j]-'a'; 88 add(c,j); 89 while (!query(r[ch[k][c]],1,n,a+l,b)){ 90 if (--l<0)break; 91 if (l==len[fa[k]])k=fa[k]; 92 } 93 if (l<0)k=1; 94 else k=ch[k][c]; 95 } 96 ans=0; 97 for(int j=x;j<=V;j++)ans+=max(0,len[j]-max(len[fa[j]],pp[pos[j]])); 98 printf("%lld\n",ans); 99 } 100 }