codeforces 163E e-Government

AC 自動機+fail樹DFS序+樹狀數組

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;

#define N 1000010

int n,m,DFS_tot,Size,S_tot;
struct Node{
    int to,next;
}edge[N*2];
int l[N],r[N],sum[N],head[N],id[N];
bool flag[N];

inline int lowbit(int x)
{
    return x&(-x);
}

void Add(int x,int val)
{
    for(int i=x;i<=Size;i+=lowbit(i))
        sum[i]+=val;
}

int Sum(int x)
{
    int Nowsum=0;
    for(int i=x;i>0;i-=lowbit(i))
        Nowsum+=sum[i];
    return Nowsum;
}

void Addedge(int u,int v)
{
    S_tot++;edge[S_tot].next=head[u];edge[S_tot].to=v;head[u]=S_tot;
}

void DFS(int k)
{
    l[k]=++DFS_tot;
    for(int i=head[k];i;i=edge[i].next)
    {
        int v=edge[i].to;
        DFS(v);
    }
    r[k]=DFS_tot;
}

struct AcAuto{
    int next[N][26],fail[N],end[N];
    int tot,root;
    int New_node()
    {
        for(int i=0;i<26;i++)
            next[tot][i]=-1;
        end[tot++]=0;
        return tot-1;
    }
    void Init()
    {
        tot=0;
        root=New_node();
    }
    void Insert(char *T,int _id)
    {
        int len=(int)strlen(T);
        int now=root;
        for(int i=0;i<len;i++)
        {
            int num=T[i]-'a';
            if(next[now][num]==-1)
                next[now][num]=New_node();
            now=next[now][num];
        }
        end[now]=1;
        id[_id]=now;
    }
    void Build_Failtree()
    {
        queue<int>Q;
        fail[root]=root;
        for(int i=0;i<26;i++)
        {
            if(next[root][i]==-1)
                next[root][i]=root;
            else
            {
                fail[next[root][i]]=root;
                Q.push(next[root][i]);
            }
        }
        while(!Q.empty())
        {
            int now=Q.front();Q.pop();
            end[now]+=end[fail[now]];
            for(int i=0;i<26;i++)
            {
                if(next[now][i]==-1)
                    next[now][i]=next[fail[now]][i];
                else
                {
                    fail[next[now][i]]=next[fail[now]][i];
                    Q.push(next[now][i]);
                }
            }
        }
    }
    void Query(char *T)
    {
        int Ans=0;
        int len=(int)strlen(T);
        int now=root;
        for(int i=0;i<len;i++)
        {
            int num=T[i]-'a';
            now=next[now][num];
            if(end[now])
                Ans+=Sum(l[now]);
        }
        printf("%d\n",Ans);
        return;
    }
};

AcAuto A;
char S[N];

int main()
{
    scanf("%d%d",&m,&n);
    A.Init();
    for(int i=1;i<=n;i++)
    {
        scanf("%s",S);
        A.Insert(S,i);
    }
    A.Build_Failtree();
    Size=A.tot;
    for(int i=0;i<A.tot;i++)
    {
        if(A.fail[i]!=i)
            Addedge(A.fail[i],i);
    }
    DFS(A.root);
    for(int i=0;i<Size;i++)
    {
        Add(l[i],A.end[i]);Add(l[i]+1,-A.end[i]);
    }
    char Ch;
    for(int i=1;i<=m;i++)
    {
        scanf(" %c",&Ch);
        if(Ch=='?')
        {
            scanf("%s",S);
            A.Query(S);
        }
        else if(Ch=='+')
        {
            int num;scanf("%d",&num);
            if(flag[num])
            {
                flag[num]^=1;
                Add(l[id[num]],1);Add(r[id[num]]+1,-1);
            }
        }
        else
        {
            int num;scanf("%d",&num);
            if(!flag[num])
            {
                flag[num]^=1;
                Add(l[id[num]],-1);Add(r[id[num]]+1,1);
            }
        }
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章