• 【HDU 5566】—Clarke and room(Ac自动机+树链剖分)


    传送门

    感觉像以前做过的一道题的简化版

    而且可以离线做
    这样时空复杂度都会小很多

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<20|1;
    inline char gc(){
        static char ibuf[RLEN],*ib,*ob;
        (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
        return (ob==ib)?EOF:*ib++;
    }
    #define gc getchar
    inline int read(){
        char ch=gc();
        int res=0,f=1;
        while(!isdigit(ch))f^=ch=='-',ch=gc();
        while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
        return f?res:-res;
    }
    #define ll long long
    #define re register
    #define pii pair<int,int>
    #define pic pair<int,char>
    #define fi first
    #define se second
    #define pb push_back
    #define cs const
    #define bg begin
    #define poly vector<int>
    #define chemx(a,b) ((a)<(b)?(a)=(b):0)
    #define chemn(a,b) ((a)>(b)?(a)=(b):0)
    cs int N=100005;
    namespace Ac{
        int fail[N],nxt[N][26],val[N],tot;
        inline void clear(){
            for(int i=0;i<=tot;i++)val[i]=0,memset(nxt[i],0,sizeof(nxt[i])),fail[i]=0;
            tot=0;
        }
        inline void insert(cs vector<int> &s){
            int len=s.size(),p=0;
            for(int c:s){
                if(!nxt[p][c])nxt[p][c]=++tot;
                p=nxt[p][c];
            }
            val[p]=len;
        }
        queue<int> q;
        inline void build(){
            for(int i=0;i<26;i++)
            if(nxt[0][i])q.push(nxt[0][i]);
            while(!q.empty()){
                int p=q.front();q.pop();
                chemx(val[p],val[fail[p]]);
                for(int c=0;c<26;c++){
                    int v=nxt[p][c];
                    if(v)fail[v]=nxt[fail[p]][c],q.push(v);
                    else nxt[p][c]=nxt[fail[p]][c];
                }
            }
        }
        inline int query(cs vector<int> &s){
            int p=0,res=0;
            for(int c:s){
                p=nxt[p][c];
                chemx(res,val[p]);
            }
            return res;
        }
    }
    vector<int>s[N],q[N],e[N];
    int fa[N],top[N],dfn,in[N],out[N],dep[N],idx[N],siz[N],son[N];
    int ans[N],n,m;
    char str[N];
    namespace Seg{
        vector<int> ask[N<<2];
        #define lc (u<<1)
        #define rc ((u<<1)|1)
        #define mid ((l+r)>>1)
        void update(int u,int l,int r,int st,int des,int k){
            if(st<=l&&r<=des)return ask[u].pb(k);
            if(st<=mid)update(lc,l,mid,st,des,k);
            if(mid<des)update(rc,mid+1,r,st,des,k);
        }
        void dfs(int u,int l,int r){
            if(ask[u].size()){
                Ac::clear();
                for(int i=l;i<=r;i++)Ac::insert(s[idx[i]]);
                Ac::build();
                for(int &x:ask[u]){
                    chemx(ans[x],Ac::query(q[x]));
                }
                ask[u].clear();
            }
            if(l==r)return;
            dfs(lc,l,mid),dfs(rc,mid+1,r);
        }
    }
    inline void updatepath(int u,int v,int k){
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]])swap(u,v);
            Seg::update(1,1,n,in[top[u]],in[u],k);
            u=fa[top[u]];
        }
        if(dep[u]<dep[v])swap(u,v);
        Seg::update(1,1,n,in[v],in[u],k);
    }
    void dfs1(int u){
        siz[u]=1,son[u]=0;
        for(int &v:e[u]){
            dep[v]=dep[u]+1;
            dfs1(v),siz[u]+=siz[v];
            if(siz[v]>siz[son[u]])son[u]=v;
        }
    }
    void dfs2(int u,int tp){
        top[u]=tp,in[u]=++dfn,idx[dfn]=u;
        if(son[u])dfs2(son[u],tp);
        for(int &v:e[u]){
            if(v==son[u])continue;
            dfs2(v,v);
        }
        out[u]=dfn;
    }
    inline void clear(){
        for(int i=1;i<=n;i++)s[i].clear(),e[i].clear();
        for(int i=1;i<=m;i++)q[i].clear(),ans[i]=0;
        dfn=0;
    }
    int main(){
        int T=read();
        while(T--){
            clear(),n=read();
            for(int i=1;i<=n;i++){
                scanf("%s",str+1);
                for(int j=1,len=strlen(str+1);j<=len;j++){
                    s[i].pb(str[j]-'a');
                }
            }
            for(int i=2;i<=n;i++)fa[i]=read(),e[fa[i]].pb(i);
            dfs1(1),dfs2(1,1);
            m=read();
            for(int i=1;i<=m;i++){
                int u=read(),v=read();
                scanf("%s",str+1);
                updatepath(u,v,i);
                for(int j=1,len=strlen(str+1);j<=len;j++){
                    q[i].pb(str[j]-'a');
                }
            }
            Seg::dfs(1,1,n);
            for(int i=1;i<=m;i++)cout<<ans[i]<<'
    ';
        }
    }
    
  • 相关阅读:
    利用正则表达式去掉html代码
    TYPE='application/xshockwaveflash'
    SQL存储过程事务和优化方法(包括查询方式语句结合)
    C#中Bitmap类实现对图像操作的一些方法
    回首往事,碩果累累,展望未來,信心滿懷。
    此方法用于确认用户输入的不是恶意信息
    js去除字符串中的空格
    SQLServer存储过程中的简单事务处理
    SQL 2000中行加入序号用法
    C#中将byte数组转换为8bit灰度图像
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328450.html
Copyright © 2020-2023  润新知