【BZOJ2754】喵星球上的点名(AC自动机)

【BZOJ2754】喵星球上的点名(AC自动机)

题面

BZOJ

题解

友情提示:此题请不要在cogs上提交,它的数据有毒

对于点名串构建\(AC\)自动机
然后把名字丢进去进行匹配,
大力统计一下答案即可
当然,要用\(map\)记录\(trie\)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 52000
inline int read()
{
    RG int x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
void ReadStr(vector<int> &a)
{
	int x=read();
	a.resize(x+1);
	a[0]=x;
	for(int i=1;i<=x;++i)a[i]=read();
}
vector<int> nam[MAX],fam[MAX];
vector<int> sub[MAX];
map<int,int>::iterator it;
int n,m;
struct Node
{
	map<int,int> son;
	int ff,fl;
	set<int> lst;
}t[MAX<<2];
int tot,vis[MAX],ans1[MAX],ans2[MAX];
void insert(vector<int> a,int g)
{
	int now=0;
	for(int i=1;i<=a[0];++i)
	{
		if(!t[now].son[a[i]])
			t[now].son[a[i]]=++tot;
		now=t[now].son[a[i]];
	}
	t[now].lst.insert(g);
	t[now].fl=1;
}
void BuildFail()
{
	queue<int> Q;
	for(it=t[0].son.begin();it!=t[0].son.end();++it)Q.push(it->second);
	while(!Q.empty())
	{
		int u=Q.front();Q.pop();
		if(!t[u].son.size())continue;
		for(it=t[u].son.begin();it!=t[u].son.end();++it)
		{
			int v=it->second,c=it->first,p=t[u].ff;
			while(p&&!t[p].son[c])p=t[p].ff;
			if(t[p].son[c])t[v].ff=t[p].son[c];
			Q.push(v);
			t[v].fl|=t[t[v].ff].fl;
		}
	}
}
void Work(vector<int> a,int str)
{
	int now=0;
	for(int i=1;i<=a[0];++i)
	{
		int c=a[i];
		if(t[now].son[c])now=t[now].son[c];
		else
		{
			while(now&&!t[now].son[c])now=t[now].ff;
			if(t[now].son[c])now=t[now].son[c];
		}
		if(t[now].fl)
		{
			int p=now;
			while(p)
			{
				
				for(set<int>::iterator it=t[p].lst.begin();it!=t[p].lst.end();++it)
					if(vis[*it]!=str){ans1[*it]++;ans2[str]++;vis[*it]=str;}
				p=t[p].ff;
			}
		}
	}
}
int main()
{
	n=read();m=read();
	for(int i=1;i<=n;++i)
	{
		ReadStr(nam[i]);
		ReadStr(fam[i]);
	}
	for(int i=1;i<=m;++i)ReadStr(sub[i]);
	for(int i=1;i<=m;++i)insert(sub[i],i);
	BuildFail();
	for(int str=1;str<=n;++str)
	{
		Work(nam[str],str);
		Work(fam[str],str);
	}
	for(int i=1;i<=m;++i)printf("%d\n",ans1[i]);
	for(int i=1;i<=n;++i){printf("%d",ans2[i]);(i==n)?putchar('\n'):putchar(' ');}
	return 0;
}


posted @ 2018-02-25 09:29  小蒟蒻yyb  阅读(472)  评论(19编辑  收藏  举报