ICode9

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

G. Death DBMS(查询每个主串和n个模板串匹配后val最大值,支持单点更新)

2020-10-29 22:33:42  阅读:240  来源: 互联网

标签:主串 DBMS Death int res dfn fail buf 节点


题:https://codeforces.com/contest/1437/problem/G

题意:首先给定n个模式串,每个模式串一开始价值为0,支持q个查询:

  • [1, x, val ]:将x位置的模式串价值改为val;
  • [2, s ] :找出在主串s中能匹配的模式串的最大值

分析:

  • 将建立n个模式串的ac自动机,然后建立fail树;
  • 因为沿fail树向下走的感觉就是找更长的“后缀”,那么到最长后缀为止,所有可能后缀都在根节点到当前点上;
  • 所以询问就是(主串在trie上跑的每个节点映射到fail树上的)节点到fail树的根路径上的信息最大值;
  • 那么更新就是fail树上单点更新;
  • 那么要高效维护查询操作,就是对树进行树剖+线段树;
  • 因为可能会存在相同模式串,在trie上同时指向一个节点,所以要处理一下相同的情况
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
const int M=3e5+5;
int tr[M<<2];
const int maxn=26;
int trie[M][maxn],fail[M],las[M],sz[M],tp[M],son[M],id[M],dfn[M],rdfn[M],fa[M];
char s[M];
vector<int>g[M];
multiset<int>mx[M];
int tot;
struct AC{
    int cnt=0;
    void Insert(char buf[],int sign){
        int len=strlen(buf),now=0;
        for(int i=0;i<len;i++){
            int x=buf[i]-'a';
            if(!trie[now][x])
                trie[now][x]=++cnt;
            now=trie[now][x];
        }
        mx[now].insert(0);
        id[sign]=now;
    }
    void getfail(){
        queue<int>que;
        while(!que.empty()) que.pop();
        for(int i=0;i<maxn;i++)
            if(trie[0][i]){
                fail[trie[0][i]]=0;
                que.push(trie[0][i]);
            }
        while(!que.empty()){
            int now=que.front();
            que.pop();
            for(int i=0;i<maxn;i++)
                if(trie[now][i]){
                    fail[trie[now][i]]=trie[fail[now]][i];
                    que.push(trie[now][i]);
                }
                else
                    trie[now][i]=trie[fail[now]][i];
        }
    }
}ac;
void dfs1(int u,int f){
    fa[u]=f,sz[u]=1;
    for(auto v:g[u]){
        if(v!=f){
            dfs1(v,u);
            sz[u]+=sz[v];
            if(!son[u]||sz[son[u]]<sz[v]) son[u]=v;
        }

    }
}
void dfs2(int u,int top){
    tp[u]=top;
    dfn[u]=++tot;
    rdfn[tot]=u;
    if(son[u])
        dfs2(son[u],top);
    for(auto v:g[u])
        if(v!=fa[u]&&v!=son[u])dfs2(v,v);
}
void up(int root){ tr[root]=max(tr[root<<1],tr[root<<1|1]); }
void build(int root,int l,int r){
    tr[root]=-1;
    if(l==r){
        tr[root]=*mx[rdfn[l]].rbegin();
        return ;
    }
    int midd=(l+r)>>1;
    build(lson);
    build(rson);
    up(root);
}
void update(int pos,int c,int root,int l,int r){
    if(l==r){
        tr[root]=c;
        return ;
    }
    int midd=(l+r)>>1;
    if(pos<=midd)
        update(pos,c,lson);
    else
        update(pos,c,rson);
    up(root);
}
int query(int L,int R,int root,int l,int r){
    if(L<=l&&r<=R){
        return tr[root];
    }
    int midd=(l+r)>>1;
    int res=-1;
    if(L<=midd) res=query(L,R,lson);
    if(R>midd) res=max(res,query(L,R,rson));
    return res;
}
int trquery(int u){
    int res=-1;
    while(tp[u]!=0){
        res=max(res,query(dfn[tp[u]],dfn[u],1,1,tot));
        u=fa[tp[u]];
    }
    res=max(res,query(dfn[0],dfn[u],1,1,tot));
    return res;
}
int solve(char buf[]){
    int len=strlen(buf),now=0;
    int ans=-1;
    for(int i=0;i<len;i++){
        now=trie[now][buf[i]-'a'];
        ans=max(ans,trquery(now));
    }
    return ans;
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",s);
        ac.Insert(s,i);
    }
    ac.getfail();
    mx[0].insert(-1);
    for(int i=1;i<=ac.cnt;i++){
        g[fail[i]].pb(i);
        mx[i].insert(-1);
    }
    dfs1(0,-1);
    dfs2(0,0);
    build(1,1,tot);
    for(int i=1;i<=m;i++){
        int op;
        scanf("%d",&op);
        if(op==1){
            int x,val;
            scanf("%d%d",&x,&val);
            ///可能会出现相同的模式串,只要最大的那个
            ///更新时要记录上个更新值,用来下次更新时删除掉(也就是“覆盖”)
            mx[id[x]].erase(mx[id[x]].find(las[x]));
            las[x]=val;
            mx[id[x]].insert(las[x]);
            update(dfn[id[x]],*mx[id[x]].rbegin(),1,1,tot);
        }
        else{
            scanf("%s",s);
            printf("%d\n",solve(s));
        }
    }
    return 0;
}
View Code

 

标签:主串,DBMS,Death,int,res,dfn,fail,buf,节点
来源: https://www.cnblogs.com/starve/p/13899655.html

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

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

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

ICode9版权所有