UVA - 10829 L-Gap Substrings (后缀自动机+线段树启发式合并)

题意:统计一段字符串中形如UVU的子串个数(其中V的长度固定为g)。

问题等价于求满足$g+1\leqslant |j-i|\leqslant g+LCP(i,j)$的后缀(i,j)的对数,即$\sum\limits_{i

由于将原串反转后的后缀(i,j)的LCP等于其在原串的后缀自动机上对应结点的LCA的最大长度,可以枚举LCA,在fail树上将right数组启发式合并即可。

 1 #include
 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||rreturn 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'a',i);
71         solve();
72         printf("Case %d: %d\n",++ka,ans[1]);
73     }
74     return 0;
75 }

 

转载于:https://www.cnblogs.com/asdfsag/p/11534125.html

你可能感兴趣的:(UVA - 10829 L-Gap Substrings (后缀自动机+线段树启发式合并))