zoukankan      html  css  js  c++  java
  • [校内训练2021_02_25]C

    题目大意:给出一个字符串,对于它的每个前缀S,求出S所有子串(不要求本质不同)的所有前缀在border树上的(深度-1)的和。例如
    ,对于字符串abab,它的第四个前缀S4=abab,有子串a,b,a,b,ab,ba,ab,aba,bab,abab,他们的所有前缀在border树上的(深度-1)的和分别是0,0,0,0,0,0,0,1,1,2,因此答案是4。

    对于一个串S,它的所有前缀在border树上的(深度-1)的和,等于它的所有前缀在S中出现次数减去|S|。因为考虑任意一个前缀和这个前缀在后面某个位置出现的位置,必然存在一个border让其产生1的贡献。

    对于一个串S,它的所有子串的所有前缀在border树上的(深度-1)的和,等于对于所有本质不同的字符串S,$ binom{cnt_S}{2}$之和,其中$cnt_S$表示S的出现次数。因为考虑任意两个位置不同的相同子串,必然存在一个border让其产生1的贡献。

    因此,暴力的方法是对于每一个前缀,建立后缀树,并在每个节点上统计$ binom{sum_u}{2}*(len_{u}-len_{fa})$的和。

    考虑每次加一个字符的过程,相当于是选择一条从一个点到根的路径,将路径上所有点的sum加一,而答案仅仅是一个关于x的二次函数。我们对于每个点维护$f(x)=ax^2+bx+c$,并规定最终的答案为$x=0$时$f(x)$的值。显然路径加满足结合律,用树剖或lct即可。

      1 #include<bits/stdc++.h>
      2 #define mod 1000000007
      3 #define G2 500000004
      4 using namespace std;
      5 typedef long long int ll;
      6 const int maxn=3E5+5;
      7 int n;
      8 string str;
      9 ll ans;
     10 namespace SAM
     11 {
     12     struct node
     13     {
     14         int fa,len,ch[26];
     15     }t[maxn*2];
     16     int tot=1,last=1;
     17     int where[maxn],sum[maxn],minPos[maxn];
     18     inline void add(int x,int id)
     19     {
     20         int now=++tot,u=last;
     21         t[now].len=t[u].len+1;
     22         last=tot;
     23         where[id]=now;
     24         minPos[now]=id;
     25         for(;u&&!t[u].ch[x];u=t[u].fa)
     26             t[u].ch[x]=now;
     27         if(!u)
     28             t[now].fa=1;
     29         else
     30         {
     31             int v=t[u].ch[x];
     32             if(t[v].len==t[u].len+1)
     33                 t[now].fa=v;
     34             else
     35             {
     36                 int w=++tot;
     37                 t[w]=t[v];
     38                 t[w].len=t[u].len+1;
     39                 t[now].fa=t[v].fa=w;
     40                 for(;u&&t[u].ch[x]==v;u=t[u].fa)
     41                     t[u].ch[x]=w;
     42             }
     43         }
     44     }
     45 }
     46 struct info
     47 {
     48     ll a,b,c;
     49     info(ll A=0,ll B=0,ll C=0):a(A),b(B),c(C){};
     50     info operator*(const int&d)
     51     {
     52         info A;
     53         A.a=a;
     54         A.b=(b+a*d*2%mod)%mod;
     55         A.c=((a*d+b)%mod*d%mod+c)%mod;
     56         return A;
     57     }
     58     info operator+(const info&A)
     59     {
     60         info B;
     61         B.a=(a+A.a)%mod;
     62         B.b=(b+A.b)%mod;
     63         B.c=(c+A.c)%mod;
     64         return B;
     65     }
     66 };
     67 namespace LCT
     68 {
     69     int fa[maxn],son[maxn][2];
     70     info ans[maxn],val[maxn];
     71     int tag[maxn];
     72     inline bool notroot(int x)
     73     {
     74         return son[fa[x]][0]==x||son[fa[x]][1]==x;
     75     }
     76     inline void pushup(int x)
     77     {
     78         ans[x]=ans[son[x][0]]+ans[son[x][1]]+val[x];
     79     }
     80     inline void rotate(int x)
     81     {
     82         int y=fa[x];
     83         int c=son[y][0]==x;
     84         fa[x]=fa[y];
     85         son[y][!c]=son[x][c];
     86         if(son[x][c])
     87             fa[son[x][c]]=y;
     88         if(notroot(y))
     89             son[fa[y]][son[fa[y]][1]==y]=x;
     90         son[x][c]=y;
     91         fa[y]=x;
     92         pushup(y);
     93         pushup(x);
     94     }
     95     inline void put(int x,const int&d)
     96     {
     97         tag[x]+=d;
     98         val[x]=val[x]*d;
     99         ans[x]=ans[x]*d;
    100     }
    101     inline void pushdown(int x)
    102     {
    103         int d=tag[x]; 
    104         tag[x]=0;
    105         put(son[x][0],d),put(son[x][1],d);
    106     }
    107     void down(int x)
    108     {
    109         if(!notroot(x))
    110         {
    111             pushdown(x);
    112             return;
    113         }
    114         down(fa[x]);
    115         pushdown(x);
    116     }
    117     inline void splay(int x)
    118     {
    119         down(x);
    120         while(notroot(x))
    121         {
    122             int y=fa[x];
    123             if(!notroot(y))
    124                 rotate(x);
    125             else if((son[fa[y]][1]==y)==(son[y][1]==x))
    126                 rotate(y),rotate(x);
    127             else
    128                 rotate(x),rotate(x);
    129         }
    130     }
    131     ll now;
    132     inline ll add(int u)
    133     {
    134         splay(u);
    135         son[u][1]=0;
    136         pushup(u);
    137         while(fa[u])
    138         {
    139             int y=fa[u];
    140             splay(y);
    141             son[y][1]=u;
    142             pushup(y);
    143             u=y;
    144         }
    145         splay(u);
    146         ll x=ans[u].c;
    147         put(u,1);
    148         now=(now+ans[u].c-x+mod)%mod;
    149         return now;
    150     }
    151     inline void init()
    152     {
    153         using namespace SAM;
    154         for(int i=1;i<=SAM::tot;++i)
    155         {
    156             ll d=(t[i].len-t[t[i].fa].len);
    157             ans[i]=val[i]=info(G2*d%mod,(mod-G2)*d%mod,0);
    158             fa[i]=t[i].fa;
    159         }
    160     }
    161 }
    162 int main()
    163 {
    164     ios::sync_with_stdio(false);
    165     cin>>n>>str;
    166     for(int i=0;i<n;++i)
    167         SAM::add(str[i]-'a',i);
    168     LCT::init();
    169     ll tot=0;
    170     for(int i=0;i<n;++i)
    171     {
    172         int pos=SAM::where[i];
    173         ans=((ans+LCT::add(pos)%mod+mod)%mod+mod)%mod;
    174         cout<<ans<<'
    ';
    175     }
    176     return 0;
    177 }
    View Code
  • 相关阅读:
    大的FIbonacci数列_Java求法
    HDU1134_Game of Connections 卡特兰数
    oracle中查询锁表
    SpringBoot之使用Druid连接池以及SQL监控和spring监控
    用vue封装插件并发布到npm
    vue 预览 Excel 表格
    vue + elementUI 表格 底部 合计总数
    springboot项目中实现访问druid内置监控页面
    解决Elementui eltable合计 showsummary不显示,样式混乱问题
    Druid连接池:慢查询监控
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/14449558.html
Copyright © 2011-2022 走看看