AC日记——[SCOI2012]喵星球上的点名 bzoj 2754

2754

 

思路:

  AC自动机暴力处理匹配;

  强大的ac自动机,强大的fail树,强大的map,强大的vector,强大的指针;

 

代码:

#include <map>
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define maxn 80005
#define maxm 200005
#define maxlen 400005

struct TreeNodeType {
    int tag,id;
    
    TreeNodeType *fail;
    
    map<int,TreeNodeType*>next;

    TreeNodeType()
    {
        tag=0,id=0,fail=NULL,next.clear();
    }
};
struct TreeNodeType *que[maxlen],*root;

int n,m,tot,ans2[maxn],ans1[maxn];

map<int,bool>vis;

vector<int>name[maxn],times[maxm];

inline void in(int &now)
{
    char Cget=getchar();now=0;
    while(Cget>'9'||Cget<'0') Cget=getchar();
    while(Cget>='0'&&Cget<='9')
    {
        now=now*10+Cget-'0';
        Cget=getchar();
    }
}

int main()
{
    freopen("name.in","r",stdin);
    freopen("name.out","w",stdout);
    root=new TreeNodeType,root->id=++tot;
    in(n),in(m);int len,pos;
    for(int i=1;i<=n;i++)
    {
        in(len);
        for(int j=1;j<=len;j++) in(pos),name[i].push_back(pos);
        name[i].push_back(-1),in(len);
        for(int j=1;j<=len;j++) in(pos),name[i].push_back(pos);
        name[i].push_back(-2);
    }
    for(int i=1;i<=m;i++)
    {
        in(len);TreeNodeType *now=root;
        for(int j=1;j<=len;j++)
        {
            in(pos);
            if(now->next[pos]==NULL)
            {
                now->next[pos]=new TreeNodeType;
                now->next[pos]->id=++tot;
            }
            now=now->next[pos];
        }
        now->tag++,times[now->id].push_back(i);
    }
    int h=0,tail=1;que[h]=root;
    while(h<tail)
    {
        TreeNodeType *now=que[h++],*temp=NULL;
        for(map<int,TreeNodeType*>::iterator it=now->next.begin();it!=now->next.end();it++)
        {
            if(now==root) it->second->fail=root;
            else
            {
                temp=now->fail;
                while(temp!=NULL)
                {
                    if(temp->next[it->first])
                    {
                        it->second->fail=temp->next[it->first];
                        break;
                    }
                    temp=temp->fail;
                }
                if(temp==NULL) it->second->fail=root;
            }
            que[tail++]=it->second;
        }
    }
    for(int i=1;i<=n;i++)
    {
        len=name[i].size(),vis.clear();
        TreeNodeType *now=root,*temp;
        for(int j=0;j<len;j++)
        {
            if(!vis[now->id])
            {
                vis[now->id]=true;
                if(now->tag)
                {
                    ans2[i]+=now->tag;
                    for(int v=0;v<times[now->id].size();v++) ans1[times[now->id][v]]++;
                }
                TreeNodeType *temp=now->fail;
                while(temp!=NULL)
                {
                    if(!vis[temp->id])
                    {
                        vis[temp->id]=true;
                        if(temp->tag)
                        {
                            ans2[i]+=temp->tag;
                            for(int v=0;v<times[temp->id].size();v++) ans1[times[temp->id][v]]++;
                        }
                    }
                    temp=temp->fail;
                }
            }
            if(now->next[name[i][j]]) now=now->next[name[i][j]];
            else
            {
                temp=now->fail;
                while(temp!=NULL)
                {
                    if(!vis[temp->id])
                    {
                        vis[temp->id]=true;
                        if(temp->tag)
                        {
                            ans2[i]+=temp->tag;
                            for(int v=0;v<times[temp->id].size();v++) ans1[times[temp->id][v]]++;
                        }
                    }
                    if(temp->next[name[i][j]])
                    {
                        now=temp->next[name[i][j]];
                        TreeNodeType *pos=temp->fail;
                        while(pos!=NULL)
                        {
                            if(!vis[pos->id])
                            {
                                vis[pos->id]=true;
                                if(pos->tag)
                                {
                                    ans2[i]+=pos->tag;
                                    for(int v=0;v<times[pos->id].size();v++) ans1[times[pos->id][v]]++;
                                }
                            }
                            pos=pos->fail;
                        }
                        break;
                    }
                    temp=temp->fail;
                }
                if(temp==NULL) now=root;
            }
        }
    }
    for(int i=1;i<=m;i++) printf("%d\n",ans1[i]);
    for(int i=1;i<=n;i++)
    {
        if(i==1) printf("%d",ans2[i]);
        else printf(" %d",ans2[i]);
    }
    return 0;
}

 

posted @ 2017-05-15 21:30  IIIIIIIIIU  阅读(224)  评论(0编辑  收藏  举报