zoukankan      html  css  js  c++  java
  • 【BZOJ3238】【AHOI2013】差异

    sam好,好写好调好ac!

    原题:

    图片题面好评

    2<=N<=500000

    在syq大神的指点下终于理解一道后缀自动姬了quq

    (其实是因为这道题的dp主要是在后缀树(就是拓扑序)上搞树形dp……

    恩sam有个好玩的东西呢就是搞出后缀自动姬后根据max搞一个类似与后缀数组中countrank的东西

    这个就是自动姬的拓扑序,同时也是parent树的不知道什么序,反正如果倒叙遍历这个序列的话x一定会比father[x]先访问到就对了

    然后就可以直接用countrank搞树形dp辣

    每个树点对答案的贡献就是(max[x]-max[father[x]])*C_{|right[x]|}^{2}

    写到这里我突然发现这个组合数不太理解啊,如果两个节点在同一个子节点的子树中怎么办……

    一定是还有什么性质我没考虑到

    syq回寝吃泡面了,只能回去问syq了quq

    啊,syq吃完泡面后讲明白了quq

    就像下面酱紫一个图:

    在这个后缀树中,现在计算2节点对于答案的贡献

    我本来的想法是如果直接用2的深度乘C_{子树大小}^{2}岂不是会出现两个节点在同一子节点的子树中然后重复计算的情况?
    但是实际上在计算贡献的时候是用(max[x]-max[father[x]])乘组合数的,这个表示的是2和1之间的连边,而不是2的深度

    2和1对答案的贡献显然就乘C_{子树大小}^{2}

    这样就解决了Σlcp(i,j)*2的问题,至于前面那些东西,最后结果是(n+1)*(n-1)*n/2,请同学们自行推到 _(:3 」∠)_

    代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 using namespace std;
     7 #define ll long long
     8 int rd(){int z=0,mk=1;  char ch=getchar();
     9     while(ch<'0'||ch>'9'){if(ch=='-')mk=-1;  ch=getchar();}
    10     while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0';  ch=getchar();}
    11     return z*mk;
    12 }
    13 char s[510000];  int n;
    14 int nxt[1100000][26],fa[1100000],mx[1100000],sz[1100000],sm[1100000];
    15 int lst=1,tt=1;
    16 int cnt[1100000],cntrk[1100000];
    17 void ist(int x){
    18     int p=lst,np=lst=++tt;
    19     mx[np]=mx[p]+1;  sz[np]=sm[np]=1;
    20     while(!nxt[p][x] && p)  nxt[p][x]=np,p=fa[p];
    21     if(!p)  fa[np]=1;
    22     else{
    23         int q=nxt[p][x];
    24         if(mx[p]+1==mx[q])  fa[np]=q;
    25         else{
    26             int nq=++tt;  mx[nq]=mx[p]+1;
    27             memcpy(nxt[nq],nxt[q],sizeof(nxt[q]));
    28             fa[nq]=fa[q];  fa[q]=fa[np]=nq;
    29             while(nxt[p][x]==q)  nxt[p][x]=nq,p=fa[p];
    30         }
    31     }
    32 }
    33 void gtcntrk(){
    34     for(int i=1;i<=tt;++i)  ++cnt[mx[i]];
    35     for(int i=1;i<=n;++i)  cnt[i]+=cnt[i-1];
    36     for(int i=tt;i;--i)  cntrk[cnt[mx[i]]--]=i;
    37 }
    38 ll play(){
    39     ll bwl=0;
    40     for(int i=tt;i;--i){
    41         sz[fa[cntrk[i]]]+=sz[cntrk[i]];
    42         /*bwl+=(ll)sm[fa[cntrk[i]]]*sz[cntrk[i]]*mx[fa[cntrk[i]]];
    43         sm[fa[cntrk[i]]]+=sz[cntrk[i]];*/
    44         bwl+=(ll)(mx[cntrk[i]]-mx[fa[cntrk[i]]])*sz[cntrk[i]]*(sz[cntrk[i]]-1);
    45     }
    46     return bwl;
    47 }
    48 int main(){//freopen("ddd.in","r",stdin);
    49     scanf("%s",s+1);  n=strlen(s+1);
    50     for(int i=1;i<=n;++i)  ist(s[i]-'a');
    51     gtcntrk();
    52     cout<<(ll)(n+1)*n/2*(n-1)-play()<<endl;
    53     return 0;
    54 }
    View Code
  • 相关阅读:
    Spring基础知识
    Hibernate基础知识
    Struts2基础知识
    在eclipse里头用checkstyle检查项目出现 File contains tab characters (this is the first instance)原因
    java后台获取cookie里面值得方法
    ckplayer 中的style.swf 中的 style.xml 中的修改方法
    java hql case when 的用法
    Windows下Mongodb安装及配置
    Mongodb中经常出现的错误(汇总)child process failed, exited with error number
    Mac 安装mongodb
  • 原文地址:https://www.cnblogs.com/JSL2018/p/6545370.html
Copyright © 2011-2022 走看看