• 后缀树(BZOJ3238TLE)


    #include<cstdio>
    #include<cstring>
    #define LL long long 
    
     char st[500010],stt[500010];
     LL ans;
     int leafr,ndcnt=1,sidcnt,lastcre;
     int isleaf[1000010],dep[1000010],nd[1000010],l[1000010],r[1000010],des[1000010],
           next[1000010],sufchain[1000010];
    
      
     int getr(int sid){
         if (isleaf[des[sid]]) return(leafr);else return(r[sid]);
     }
     
     void cut(int po,int sid,int len){
         dep[++ndcnt]=dep[po]+len;
         isleaf[ndcnt]=0;
         
         nd[ndcnt]=++sidcnt;
         des[sidcnt]=des[sid];
         l[sidcnt]=len+l[sid];r[sidcnt]=getr(sid);next[sidcnt]=-1;des[sidcnt]=des[sid];
        des[sid]=ndcnt;r[sid]=len+l[sid]-1;
     }
     
     void ins(int po,int alph){
         dep[++ndcnt]=dep[po]+1;
         isleaf[ndcnt]=1;
         nd[ndcnt]=-1;
         
         l[++sidcnt]=alph;r[sidcnt]=alph;
         des[sidcnt]=ndcnt;next[sidcnt]=nd[po];nd[po]=sidcnt;
     }
    
     void buildtree(){
        int po=1,lastins=1;nd[1]=-1;sufchain[1]=1;int prom=0;
        
        for (int i=1;i<=strlen(st)-1;i++){
            leafr=i;int p,flag;
            prom=0;
            
            while (lastins<=i){
                
                while(1){
                    flag=0;
                    for (p=nd[po];p!=-1;p=next[p])
                    if (st[l[p]]==st[lastins+dep[po]]) break;
                    
                    if (p==-1){ins(po,i);
                               if (prom) sufchain[lastcre]=po;
                               prom=0;
                               lastcre=po;
                               break;}
                    if (i-lastins+1-dep[po]<=getr(p)-l[p]+1){
                        if (st[i]==st[l[p]+i-lastins-dep[po]]) 
                          {flag=1;
                          if (prom) sufchain[lastcre]=po;
                          prom=0;
                          lastcre=po;
                          break;}
                        if (st[i]!=st[l[p]+i-lastins-dep[po]]) {
                            cut(po,p,i-lastins-dep[po]);
                            if (prom) sufchain[lastcre]=ndcnt;
                            if (i-lastins-dep[po]>1) prom=1;else prom=0;
                            lastcre=ndcnt;sufchain[lastcre]=1;
                            ins(ndcnt,i);break;
                        }
                    }
                    if (i-lastins+1-dep[po]>getr(p)-l[p]+1) po=des[p];
                }
                if (flag) {break;}
                po=sufchain[po];lastins++;
          }
        }
     }
     
     int top=0;
     struct str{
         int po,fr;
         LL cnt,len; 
     }sta[500010];
     
          
         void pb(int ps,int le,int p){
             sta[++top].po=p;sta[top].len=le;sta[top].fr=ps;
             sta[top].cnt=0;
         }
         
        void pop(){
            if (isleaf[sta[top].po]) sta[top].cnt++;
            sta[sta[top].fr].cnt+=sta[top].cnt;
            top--;
        }
     
     void getans(){
         pb(0,0,1);top=1;
         
         int i=1;
         while (top>=i){
             int tp=i;
             for (int p=nd[sta[tp].po];p!=-1;p=next[p]) 
             pb(tp,getr(p)-l[p]+1,des[p]);
             i++;
         }
         
        while(top){
            ans-=sta[top].len*sta[top].cnt*(sta[top].cnt-1);
            pop();
        } 
     }
    
     int main(){
         scanf("%s",stt);
         
         LL len=strlen(stt);ans=(len-1)*len*(len+1)/2;
        
        st[0]=' ';
        strcat(stt,"$");strcat(st,stt);
        
        buildtree();
    
        getans();
        
        printf("%lld",ans);
      }

    注意某一个串对应点到后缀树根的深度是$O(n cdot sqrt{n})$的

  • 相关阅读:
    在Eclipse中使用JUnit4进行单元测试(上)
    SVN和Subclipse安装和使用指南汇总
    在windows下搭建SVN服务器
    学会SVN的应用源代码托管
    SVN中检出(check out) 和 导出(export) 的区别
    .NET平台三层应用程序框架搭建(一)
    Winform dataGridview 为每一个单元格制定一个tooptip
    SQL row_number() over() 来自动产生行号
    Winform datagridview 设置单元格为只读属性
    SQL 把字符创分割成两个字符串
  • 原文地址:https://www.cnblogs.com/zhujiangning/p/5570901.html
Copyright © 2020-2023  润新知