zoukankan      html  css  js  c++  java
  • BZOJ-3879: SvT

    后缀树+虚树

    做这道题我们需要知道这么几个东西

    • 两个后缀的(lcp)就是其后缀树上的(lca)

    • 用一个字符串的反串建(sam),其(parent)边就构成了原串的后缀树

    这道题要求询问(k)个后缀两两之间(lcs)之和,转化到后缀树中就是问这(k)个点任意两个点(lca)处值相加

    考虑树形(DP),计算每个点是多少对点的(LCA),然而这样时间复杂度一次(O(n)),总共(O(m*n))

    对于每一次询问的(k)个点,在后缀树上建虚树,时间复杂度就是(O(sum t))

    #include<map>
    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int maxn=1e6+100,maxm=1e6+100;
    int n,t,m,a[maxn],fa[maxn],dep[maxn],son[maxn],siz[maxn],top[maxn],bj[maxn];
    int nex[maxm],v[maxm],head[maxn],num=1,dfn[maxn],tim,tp,st[maxn],bh[maxn];
    char s[maxn];
    vector<int>e[maxn];
    void add(int x,int y){
        v[++num]=y;
        nex[num]=head[x];
        head[x]=num;
    }
    struct SAM{
        int son[maxn][26],len[maxn],fa[maxn];
        int last,tot;
        SAM(){last=tot=1;}
        void insert(int x){
            int p=last,np=++tot;
            len[np]=len[p]+1;
            while(p&&son[p][x]==0)
                son[p][x]=np,p=fa[p];
            if(!p)
                fa[np]=1;
            else{
                int q=son[p][x];
                if(len[q]==len[p]+1)
                    fa[np]=q;
                else{
                    int nq=++tot;
                    memcpy(son[nq],son[q],sizeof(son[q]));
                    fa[nq]=fa[q];
                    len[nq]=len[p]+1;
                    fa[q]=fa[np]=nq;
                    while(p&&son[p][x]==q)
                        son[p][x]=nq,p=fa[p];
                }
            } 
            last=np;
        }
        void work(){
            for(int i=2;i<=tot;i++)
                add(fa[i],i);
        }
    }sam;
    void dfs1(int x,int f,int d){
        fa[x]=f;
        dep[x]=d;
        siz[x]=1;
        dfn[x]=++tim;
        for(int i=head[x];i;i=nex[i])
            if(v[i]!=f){
                dfs1(v[i],x,d+1);
                if(siz[son[x]]<siz[v[i]])
                    son[x]=v[i];
                siz[x]+=siz[v[i]];
            }
    }
    void dfs2(int x,int tp){
        top[x]=tp;
        if(son[x]) dfs2(son[x],tp);
        for(int i=head[x];i;i=nex[i])
            if(v[i]!=fa[x]&&v[i]!=son[x])
                dfs2(v[i],v[i]);
    }
    int Lca(int x,int y){
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]])
                swap(x,y);
            x=fa[top[x]];
        }
        return dep[x]>dep[y]?y:x;
    }
    bool cmp(int x,int y){
        return dfn[x]<dfn[y];
    }
    void insert(int x){
        if(!tp){
            st[++tp]=x;
            return;
        }
        int lca=Lca(x,st[tp]);
        while(tp>1&&dfn[st[tp-1]]>=dfn[lca])
            e[st[tp-1]].push_back(st[tp]),tp--;
        if(st[tp]!=lca) e[lca].push_back(st[tp]),st[tp]=lca;
        st[++tp]=x;
    }
    ll dp(int x,ll &z){
        ll tmp=0,tot=bj[x];
        for(int i=0;i<e[x].size();i++){
            int y=e[x][i];
            tmp=dp(y,z);
            z+=tot*tmp*sam.len[x];
            tot+=tmp;
        }
        bj[x]=0;
        e[x].clear();
        return tot;
    }
    void vtree(){
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
            scanf("%d",&a[i]),a[i]=bh[a[i]],bj[a[i]]=1;
        sort(a+1,a+m+1,cmp);
        st[tp=1]=1;
        a[0]=-1;
        for(int i=1;i<=m;i++) if(a[i]!=a[i-1]) insert(a[i]);
        while(tp>1) e[st[tp-1]].push_back(st[tp]),tp--;tp--;
        ll ans=0;
        dp(1,ans);
        printf("%lld
    ",ans);
    }
    int main(){
        scanf("%d%d",&n,&t);
        scanf("%s",s+1);
        for(int i=n;i>=1;i--) sam.insert(s[i]-'a'),bh[i]=sam.last;
        sam.work();
        dfs1(1,1,1);
        dfs2(1,1);
        while(t--)
            vtree();
        return 0;
    }
    
  • 相关阅读:
    从远程库克隆(转载)
    添加远程库(转载)
    远程仓库(转载)
    maven+hudson构建集成测试平台
    maven_基本配置
    crawler_基础之_httpclient 访问网络资源
    crawler_jsoup HTML解析器_使用选择器语法来查找元素
    oracle_job 清空冗余数据 ,每一分钟执行一次
    oracle_根据ID(字符型)建立分区表
    crawler_基础之_java.net.HttpURLConnection 访问网络资源
  • 原文地址:https://www.cnblogs.com/nianheng/p/10066847.html
Copyright © 2011-2022 走看看