UVA - 10829 L-Gap Substrings (后缀自动机+线段树启发式合并)
题意:统计一段字符串中形如UVU的子串个数(其中V的长度固定为g)。
问题等价于求满足$g+1\leqslant |j-i|\leqslant g+LCP(i,j)$的后缀(i,j)的对数,即$\sum\limits_{i<j}[g+1\leqslant |j-i|\leqslant g+LCP(i,j)]$。
由于将原串反转后的后缀(i,j)的LCP等于其在原串的后缀自动机上对应结点的LCA的最大长度,可以枚举LCA,在fail树上将right数组启发式合并即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=1e5+10,M=26; 5 char s[N]; 6 int n,fa[N],go[N][M],mxl[N],last,tot,g,ss[N],c[N],ka; 7 int rt[N],ls[N*30],rs[N*30],sum[N*30],tot2,ans[N]; 8 #define mid ((l+r)>>1) 9 int newnode2() {int u=++tot2; sum[u]=ls[u]=rs[u]=0; return u;} 10 void upd(int& u,int p,int l=0,int r=n-1) { 11 if(!u)u=newnode2(); 12 sum[u]++; 13 if(l==r)return; 14 p<=mid?upd(ls[u],p,l,mid):upd(rs[u],p,mid+1,r); 15 } 16 void mg(int& u,int v) { 17 if(!u||!v) {u=u|v; return;} 18 sum[u]+=sum[v]; 19 mg(ls[u],ls[v]),mg(rs[u],rs[v]); 20 } 21 int qry(int u,int L,int R,int l=0,int r=n-1) { 22 if(l>=L&&r<=R)return sum[u]; 23 if(l>R||r<L)return 0; 24 return qry(ls[u],L,R,l,mid)+qry(rs[u],L,R,mid+1,r); 25 } 26 void dfs(int u,int v,int l=0,int r=n-1) { 27 if(!sum[v])return; 28 if(l==r) { 29 ans[u]+=qry(rt[u],l+(1+g),l+(mxl[u]+g)); 30 ans[u]+=qry(rt[u],l-(mxl[u]+g),l-(1+g)); 31 return; 32 } 33 dfs(u,ls[v],l,mid),dfs(u,rs[v],mid+1,r); 34 } 35 int newnode(int l) {int u=++tot; rt[u]=ans[u]=0,mxl[u]=l,memset(go[u],0,sizeof go[u]); return u;} 36 void add(int ch,int r) { 37 int p=last,np=last=newnode(mxl[p]+1); 38 upd(rt[np],r); 39 for(; p&&!go[p][ch]; p=fa[p])go[p][ch]=np; 40 if(!p)fa[np]=1; 41 else { 42 int q=go[p][ch]; 43 if(mxl[q]==mxl[p]+1)fa[np]=q; 44 else { 45 int nq=newnode(mxl[p]+1); 46 memcpy(go[nq],go[q],sizeof go[q]); 47 fa[nq]=fa[q],fa[q]=fa[np]=nq; 48 for(; p&&go[p][ch]==q; p=fa[p])go[p][ch]=nq; 49 } 50 } 51 } 52 void solve() { 53 for(int i=0; i<=tot; ++i)c[i]=0; 54 for(int i=1; i<=tot; ++i)++c[mxl[i]]; 55 for(int i=1; i<=tot; ++i)c[i]+=c[i-1]; 56 for(int i=1; i<=tot; ++i)ss[--c[mxl[i]]]=i; 57 for(int i=tot-1; i>=0; --i) { 58 int v=ss[i],u=fa[v]; 59 if(!u)continue; 60 if(sum[rt[v]]>sum[rt[u]])swap(rt[u],rt[v]); 61 dfs(u,rt[v]),mg(rt[u],rt[v]); 62 ans[u]+=ans[v]; 63 } 64 } 65 int main() { 66 int T; 67 for(scanf("%d",&T); T--;) { 68 scanf("%d%s",&g,s),n=strlen(s); 69 tot=tot2=0,last=newnode(0); 70 for(int i=0; i<n; ++i)add(s[i]-'a',i); 71 solve(); 72 printf("Case %d: %d\n",++ka,ans[1]); 73 } 74 return 0; 75 }