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<<"\n"
#define dd(x) cout<< #x<<" = "<<x<<" "
#define debug() cout<<"I love Miyamizu Mitsuha forever!\n"
#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)<<"\n";
    }
    return 0;
}

 

posted @ 2020-10-08 23:56  GGMU  阅读(953)  评论(0编辑  收藏  举报