zoukankan      html  css  js  c++  java
  • LOJ#6198. 谢特 SAM+启发式合并+01trie

    并不难的一道字符串题.  

    显然后缀自动机上进行字典树的启发式合并.  

    但是一定注意,题中要求的是两个后缀的 LCP 而不是两个前缀的 LCP. 

    所以在构建后缀自动机的时候要从后向前构建.  

    刚开始从前向后构建 WA 了半天.  

    然后进行启发式合并的时候可以对每个节点维护一个 id[x],如果儿子的大小大于点 $x$ 大小就 swap 一下即可.  

    code:   

    #include <cstdio>      
    #include <vector>
    #include <cstring> 
    #include <algorithm>   
    #define N 200008 
    #define ll long long 
    #define pb push_back   
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std; 
    int ans; 
    int last,tot,cnt,n,edges;   
    char str[N];    
    vector<int>se[N];   
    int hd[N],to[N],nex[N];  
    int pre[N],mx[N],ch[N][27],id[N],rt[N],val[N];     
    struct data { 
        int ch[2],si;  
    }s[N*50];    
    void add(int u,int v) { 
        nex[++edges]=hd[u];  
        hd[u]=edges,to[edges]=v;   
    } 
    void ins(int &x,int l,int v) {     
        if(!x) { 
            x=++cnt; 
        }
        if(l==-1) { 
            return;  
        }    
        int d=(v>>l)&1;     
        ins(s[x].ch[d],l-1,v),++s[s[x].ch[d]].si; 
    }        
    int query(int x,int l,int v) {    
        if(l==-1) {  
            return 0; 
        }         
        int d=1^((v>>l)&1);     
        if(s[x].ch[d]) {  
            return (1<<l)+query(s[x].ch[d],l-1,v);  
        }  
        else { 
            return query(s[x].ch[1^d],l-1,v);  
        }
    }
    void init() {  
        last=tot=1; 
        for(int i=1;i<N;++i) id[i]=i;   
    }     
    void extend(int c,int v) {  
        int np=++tot,p=last;   
        mx[np]=mx[p]+1,last=np;  
        for(;p&&!ch[p][c];p=pre[p]) ch[p][c]=np;  
        if(!p) { 
            pre[np]=1; 
        } 
        else {  
            int q=ch[p][c];  
            if(mx[q]==mx[p]+1) pre[np]=q; 
            else {  
                int nq=++tot;  
                mx[nq]=mx[p]+1; 
                memcpy(ch[nq],ch[q],sizeof(ch[q])); 
                pre[nq]=pre[q],pre[q]=pre[np]=nq;  
                for(;p&&ch[p][c]==q;p=pre[p]) ch[p][c]=nq;  
            }
        }
        se[np].pb(v);     
        ins(rt[np],22,val[v]);       
    }
    void sol(int x) {            
        int y,z; 
        for(int i=hd[x];i;i=nex[i]) {     
            y=to[i],sol(y);    
            if(se[id[x]].size()<se[id[y]].size()) {    
                swap(id[x],id[y]); 
            }   
            for(int j=0;j<se[id[y]].size();++j) {            
                int p=se[id[y]][j];   
                int tmp=mx[x]+query(rt[id[x]],22,val[p]);   
                ins(rt[id[x]],22,val[p]); 
                se[id[x]].pb(p);      
                if(tmp>ans) {   
                    ans=tmp; 
                }
            }
        }
    }
    int main() {  
        // setIO("input"); 
        init();       
        scanf("%d%s",&n,str+1);  
        for(int i=1;i<=n;++i) {
            scanf("%d",&val[i]); 
        }
        for(int i=1;i<=n;++i) { 
            extend(str[n-i+1]-'a',n-i+1);                       
        }   
        for(int i=2;i<=tot;++i) {     
            add(pre[i],i); 
        }    
        sol(1);  
        printf("%d
    ",ans);   
        return 0; 
    }
    

      

  • 相关阅读:
    dwSun带你选Python的编辑器/IDE
    ubuntu中文乱码解决
    解决matplotlib中文显示
    1506.01186-Cyclical Learning Rates for Training Neural Networks
    1503.02531-Distilling the Knowledge in a Neural Network.md
    1804.03235-Large scale distributed neural network training through online distillation.md
    mysql导入太慢解决方法
    已某个时间单位(日月周年)来分割时间段
    阿里云邮件推送
    阿里云短信推送服务
  • 原文地址:https://www.cnblogs.com/guangheli/p/13345988.html
Copyright © 2011-2022 走看看