zoukankan      html  css  js  c++  java
  • UVA

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

    问题等价于求满足$g+1leqslant |j-i|leqslant g+LCP(i,j)$的后缀(i,j)的对数,即$sumlimits_{i<j}[g+1leqslant |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
    ",++ka,ans[1]);
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    vue生命周期总结
    Generator的基本用法
    React context基本用法
    盗链
    Linux 黑白界面显示
    nginx 反向代理Apache
    apache+php windows下配置
    正则表达式匹配空行
    列表页条目不刷新删除
    linux终端自定义设置
  • 原文地址:https://www.cnblogs.com/asdfsag/p/11534125.html
Copyright © 2011-2022 走看看