题意:统计一段字符串中形如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 }