zoukankan      html  css  js  c++  java
  • codeforces 547 E.Mike and Friends(AC自动机fail树dfs序建可持久化线段树)

    传说中的对联算法套路题,先贴代码,题解咕咕咕。

    上联:AC自动机fail树dfs序建可持久化线段树

    下联:后缀自动机next指针dag图上跑SG函数

    上联这几个算法学了很久了,今天才把这题做了,虽然csl说是套路题,但感觉真的很难,下联的还差后缀自动机正在学,学好了再贴代码。

    #include<bits/stdc++.h>
     
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    typedef pair <int,int> pii;
    #define rep(i,x,y) for(int i=x;i<y;i++)
    #define rept(i,x,y) for(int i=x;i<=y;i++)
    #define per(i,x,y) for(int i=x;i>=y;i--)
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define de(x) cout<< #x<<" = "<<x<<"
    "
    #define dd(x) cout<< #x<<" = "<<x<<" "
    #define debug() cout<<"I love Miyamizu Mitsuha forever!
    "
    #define mes(a,b) memset(a,b,sizeof a)
    const int inf=0x3f3f3f3f;
    const int maxn=2e5+5;
    vector<int> v[maxn];
    int p[maxn];
    class Trie
    {
        public:
            Trie()
            {
                cnt=1;
            }
            int cnt; 
            int trie[maxn][26];
            int fail[maxn],fa[maxn];
            
            int insert(string s)
            {
                int len=s.size();
                int pos=0;
                rep(i,0,len)
                {
                    int next=s[i]-'a';
                    if(!trie[pos][next]) trie[pos][next]=cnt++;
                    fa[trie[pos][next]]=pos;
                    pos=trie[pos][next];
                }
                return pos;
            }
            void getfail()
            {
                queue<int> q;
                rep(i,0,26)
                {
                    if(trie[0][i])
                    {
                        fail[trie[0][i]]=0;
                        v[0].pb(trie[0][i]);
                        q.push(trie[0][i]);
                    }
                }
                while(!q.empty())
                {
                    int pos=q.front();
                    q.pop();
                    rep(i,0,26)
                    {
                        if(trie[pos][i])
                        {
                            fail[trie[pos][i]]=trie[fail[pos]][i];
                            v[trie[fail[pos]][i]].pb(trie[pos][i]);
                            q.push(trie[pos][i]);
                        }
                        else
                        {
                            trie[pos][i]=trie[fail[pos]][i];
                        }
                    }
                }
            }
            
    }ac;
     
    int dfsl[maxn],dfsr[maxn],dfspos=0;
    void dfs(int id)
    {
        dfsl[id]=dfsr[id]=++dfspos;
        rep(i,0,v[id].size())
        {
            dfs(v[id][i]);
            dfsr[id]=dfsr[v[id][i]];
        }
    }
     
    int root[maxn];
    class element
    {
        public:
            int lson,rson,val;
    };
    class Tree
    {
        public:
            int cnt=0;
            element tree[maxn<<5];
            int build(int l,int r)
            {
                int id=++cnt;
                tree[id].val=0;
                if(l==r) return id;
                int mid=(l+r)>>1;
                tree[id].lson=build(l,mid);
                tree[id].rson=build(mid+1,r);
                return id;
            }
            void update(int &id,int p,int lt,int rt,int plus=1)
            {
                if(lt>p||rt<p) return ;
                int newid=++cnt;
                if(lt==rt)
                {
                    tree[newid].val=tree[id].val+plus;
                    id=newid;
                    return ;
                }
                tree[newid]=tree[id];
                id=newid;
                int mid=(lt+rt)>>1;
                update(tree[newid].lson,p,lt,mid,plus);
                update(tree[newid].rson,p,mid+1,rt,plus);
                tree[newid].val=tree[tree[newid].lson].val+tree[tree[newid].rson].val;
            }
            int query(int id,int l,int r,int lt,int rt)
            {
                if(lt>=l&&rt<=r) return tree[id].val;
                if(lt>r||rt<l) return 0;
                int mid=(lt+rt)>>1;
                return query(tree[id].lson,l,r,lt,mid)+query(tree[id].rson,l,r,mid+1,rt);
            }
    }t;
    int st[maxn],cnt=0;
     
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        int n,q;
        cin>>n>>q;
        rept(i,1,n)
        {
            string s;
            cin>>s;
            p[i]=ac.insert(s);
        }
        ac.getfail();
        dfs(0);
        root[cnt++]=t.build(0,ac.cnt);
        st[0]=root[0];
        rept(i,1,n)
        {
            int pos=p[i];
            while(pos)
            {
                root[cnt+1]=root[cnt];
                cnt++;
                t.update(root[cnt],dfsl[pos],0,ac.cnt,1);
                pos=ac.fa[pos];
            }
            st[i]=root[cnt];
        }
        while(q--)
        {
            int l,r,k;
            cin>>l>>r>>k;
            cout<<t.query(st[r],dfsl[p[k]],dfsr[p[k]],0,ac.cnt)-t.query(st[l-1],dfsl[p[k]],dfsr[p[k]],0,ac.cnt)<<"
    ";
        }
        return 0;
    }
  • 相关阅读:
    结构struct 联合Union和枚举Enum的细节讨论
    ubuntu 查询 修改 时间
    在Ubuntu上下载、编译和安装Android最新内核源代码(Linux Kernel)
    浅谈Android系统开发中LOG的使用
    如何单独编译Android源代码中的模块
    在Ubuntu为Android硬件抽象层(HAL)模块编写JNI方法提供Java访问硬件服务接口
    在Ubuntu上为Android系统编写Linux内核驱动程序
    在Ubuntu上为Android系统内置Java应用程序测试Application Frameworks层的硬件服务
    在Ubuntu上为Android系统内置C可执行程序测试Linux内核驱动程序
    在Ubuntu上为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序
  • 原文地址:https://www.cnblogs.com/FZUzyz/p/13783353.html
Copyright © 2011-2022 走看看