ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P5840-[COCI2015]Divljak 题解

2021-07-18 01:01:45  阅读:190  来源: 互联网

标签:ro int 题解 COCI2015 zhi maxn lo Divljak now


P5840-[COCI2015]Divljak

200行代码。。

题意:给一些模式串和q次操作,每次可以把一个新匹配串扔进一个集合里,或者询问当前集合里所有匹配串有几个包含某模式串。

题解:首先是多模匹配,把模式串全扔到ac自动机上,建fail树。

对于操作一:匹配串扔进去后会对经过的所有节点与父节点的链上有贡献。而且就算多次跑到同一个点,由于是同一个匹配串,最多贡献只能计算为1,那么转化为在fail树上的一些点,往他们与根结点的链交集上加一。询问的时候只询问一个节点的值,链交上所有点都更新的话代价太大,考虑转化成树上差分+求带修的子树和,做法是:跑出fail树的dfs序,在链交集上把所有节点按dfs序排序,然后把所有节点权值+1,相邻节点的lca处权值-1,这样的树上差分操作才能保证正确(!)。

对于操作二:只需按dfs序建立线段树,维护权值,允许单点加减和区间查询(dfs序号到dfs+siz即为子树和)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=2e6+10;
int n,cnt=1,tot;
struct aczdj{
    int vis[30],fail,ans1;
    int end;
}ac[maxn];
int mp[maxn],rd[maxn],dfn[maxn],rdfn[maxn],siz[maxn];
vector<int> yuan[maxn];
void build1(string now,int biao){
    int now1=now.length(),now2=1;
    for(int i=0;i<now1;i++){
        int v=now[i]-'a'+1;
        if(!ac[now2].vis[v]){
            ac[now2].vis[v]=++cnt;
        }
        now2=ac[now2].vis[v];
    }
    ac[now2].end=biao;
    mp[biao]=now2;
}
void buildfail(){
    queue<int> k1;
    for(int i=1;i<=26;i++) ac[0].vis[i]=1;
    k1.push(1);
    while(!k1.empty()){
        int tmp=k1.front();k1.pop();
        int fl=ac[tmp].fail;
        for(int i=1;i<=26;i++){
            int v=ac[tmp].vis[i];
            if(!v) ac[tmp].vis[i]=ac[fl].vis[i];
            else{
                ac[v].fail=ac[fl].vis[i];
                yuan[ac[fl].vis[i]].push_back(v);
                rd[v]++;
                k1.push(v);
            }
        }
    }
}
int dep[maxn],fat[maxn][60],lg[maxn];
void dfs(int now,int fa){
    dfn[now]=++tot;rdfn[tot]=now;
    siz[now]=1;
    dep[now]=dep[fa]+1;
    fat[now][0]=fa;
    for(int i=1;i<=lg[dep[now]];i++) fat[now][i]=fat[fat[now][i-1]][i-1];
    for(int i=0;i<yuan[now].size();i++){
        int v=yuan[now][i];
        if(v==fa) continue;
        dfs(v,now);
        siz[now]+=siz[v];
    }
}
int lca(int u,int v){
    if(dep[u]>dep[v]) swap(u,v);
    while(dep[v]>dep[u]) v=fat[v][lg[dep[v]-dep[u]]-1];
    if(u==v) return u;
    for(int i=lg[dep[v]];i>=0;i--){
        if(fat[u][i]!=fat[v][i]){
            u=fat[u][i];
            v=fat[v][i];
        }
    }
    return fat[v][0];
}
struct node{
    int zhi;
}all[maxn*4];
void pushup(int now){all[now].zhi=all[now*2].zhi+all[now*2+1].zhi;}
void build(int now,int lo,int ro){
    if(lo==ro) return;
    build(now*2,lo,mid);
    build(now*2+1,mid+1,ro);
}
void upd(int now,int lo,int ro,int pos,int zhi){
    if(lo==ro&&lo==pos){
        all[now].zhi+=zhi;
        return;
    }
    if(pos<=mid) upd(now*2,lo,mid,pos,zhi);
    else upd(now*2+1,mid+1,ro,pos,zhi);
    pushup(now);
}
void acque(string &now){
    vector<int> k2;
    int now1=now.length(),now2=1;
    for(int i=0;i<now1;i++){
        int v=now[i]-'a'+1;
        now2=ac[now2].vis[v];
        k2.push_back(dfn[now2]);
    }
    sort(k2.begin(),k2.end());
    for(int i=0;i<k2.size();i++){
        if(i&&k2[i]==k2[i-1]) continue;
        upd(1,1,tot,k2[i],1);
        if(i){
            int fat1=lca(rdfn[k2[i]],rdfn[k2[i-1]]);
            upd(1,1,tot,dfn[fat1],-1);
        }
    }
}
ll req(int now,int lo,int ro,int lo1,int ro1){
    if(lo>=lo1&&ro<=ro1){
        return all[now].zhi;
    }
    if(lo>ro1||ro<lo1) return 0;
    ll ans1=0;
    if(mid>=lo1) ans1+=req(now*2,lo,mid,lo1,ro1);
    if(mid<ro1) ans1+=req(now*2+1,mid+1,ro,lo1,ro1);
    return ans1;
}
signed main(){
    for(int i=1;i<=2e6;i++){
        lg[i]=lg[i-1];
        if(i==(1<<lg[i])) lg[i]++;
    }
    cin>>n;string yuan1;
    for(int i=1;i<=n;i++){
        cin>>yuan1;
        build1(yuan1,i);
    }
    buildfail();
    dfs(1,0);
    build(1,1,tot);
    int q;cin>>q;
    while(q--){
        int a1,a2;cin>>a1;
        if(a1==1){
            string p1;cin>>p1;
            acque(p1);
        }
        else{
            cin>>a2;
            cout<<req(1,1,tot,dfn[mp[a2]],dfn[mp[a2]]+siz[mp[a2]]-1)<<endl;
        }
    }
    return 0;
}

标签:ro,int,题解,COCI2015,zhi,maxn,lo,Divljak,now
来源: https://www.cnblogs.com/14long-Alex/p/15025653.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有